In the previous blog, we discussed various contour tracing algorithms like Moore, radial sweep, etc. and then we also covered Suzuki’s algorithm, the one that OpenCV uses for border following or contour tracing. In this blog, we will discuss the builtin functions provided by OpenCV for finding and drawing contours. So, let’s get started.
Finding the contours
OpenCV provides the following builtin function for finding the contour
1 |
contours, hierarchy = cv2.findContours(image, mode, method) |
Here, the first argument “image” should be an 8-bit single-channel image. For better accuracy use a binary image. If you didn’t provide a binary image, then this method will convert it into a binary image by treating all the nonzero pixels as ‘1’ and zero remains ‘0’.
The second argument “mode” specifies how you want to retrieve the contours. This means whether you want to extract the outer contours only or retrieve contours without establishing any hierarchical relationships. Below are the several options available
- cv2.RETR_EXTERNAL – retrieves only the extreme outer contours.
- cv2.RETR_LIST – retrieves contours without establishing any hierarchical relationships.
- cv2.RETR_TREE – constructs a full hierarchy of nested contours.
- cv2.RETR_CCOMP – arranges all the contours into a 2-level hierarchy – outer contours and hole contours.
The third argument “method” denotes the contour approximation method. We don’t need to store all the points of a contour as the same thing can also be represented in a compact manner. For instance, a straight line can be represented by the endpoints. There is no need to store all the points as that would be redundant. OpenCV provides various options for this.
- cv2.CHAIN_APPROX_NONE – stores all the boundary points.
- cv2.CHAIN_APPROX_SIMPLE – removes all the redundant points and thus saves memory.
- cv2.CHAIN_APPROX_TC89_L1 – applies one of the variants of the Teh-Chin chain approximation algorithm
The first output “contours” is a Python list of all the contours in the image. Each individual contour is a Numpy array of (x,y) coordinates of boundary points of the object.
The second output “hierarchy” represents the relationship among the contours like, is it a child of some other contour, or is it a parent, etc. OpenCV represents it as an array of four values : [Next, Previous, First_Child, Parent]
- “Next denotes the next contour at the same hierarchical level.”
- “Previous denotes the previous contour at the same hierarchical level.”
- “First_Child denotes its first child contour.”
- “Parent denotes index of its parent contour.”
Depending upon the contour retrieval mode argument hierarchy array can take different values. You can read more about it here.
Drawing the Contours
OpenCV provides the following builtin function for drawing the contour.
1 |
image = cv.drawContours(image, contours, Id, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) |
The first argument is the destination image on which to draw the contours, the second argument is the contours which should be passed as a Python list, the third argument is the index of contours that we want to draw(To draw all contours, pass -1). If the thickness ≥ 0, it draws contour outlines in the image otherwise, fills the area bounded by the contours. The optional argument hierarchy and the max-level specify up to which hierarchy level to draw the contours.
Now, let’s take an example to understand the above two functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import cv2 # Load the image img = cv2.imread('D:/downloads/opencv_logo1.PNG') # Convert to grayscale img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Threshold the image to produce a binary image ret, thresh = cv2.threshold(img_gray,20,255,0) # Find the contours img2, contours, heirarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Draw the contours cv2.drawContours(img, contours, -1, (127,127,0), 2) # Display the image cv2.imshow('a1',img) cv2.waitKey(0) |
Below is the output of the above code.
Hope you enjoy reading.
If you have any doubts/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.