I am using OpenCV's cv::findContours
function to extract contours in a binary image, in particular, I'm extracting a hierarchy of contours (using the CV_RETR_CCOMP
flag). At some point in my further processing of those contours I need to rely on a consistent vertex orientation of these contours (i.e. counter-clockwise vs. clockwise).
Of course I can just determine that orientation myself using the sign of the contour's area (as computed by cv::contourArea(..., true)
), but I wonder if that is even necessary (besides that, it won't even work for contours with an area of 0, i.e. thin lines in the source image) or if cv::findContours
already guarantees a consistent orientation for the generated contours. I did check a few of the generated contours and cv::contourArea
does indeed seem to return negative values for outer contours and positive values for inner contours. However, I couldn't find any actual guarantee to this effect in the OpenCV documentation.
So, is it specifically guaranteed that the contours returned by cv::findContours
always have a consistent orientation? Is this documented anywhere? Or does it vary by version (mine is 2.4.5 for that matter)? Does the actual paper on the algorithm referenced in the documentation already say something about this? Or maybe someone with a little more insight into the actual implementation of OpenCV can say a little more about this than the interface documentation can?
To put in simple words findContours detects change in the image color and marks it as contour. As an example, the image of number written on paper the number would be detected as contour. The part that you want to detect should be white like above numbers in 1st image.
What are contours? Contours can be explained simply as a curve joining all the continuous points (along the boundary), having same color or intensity. The contours are a useful tool for shape analysis and object detection and recognition. For better accuracy, use binary images.
go through the first contour as it is listed until you hit the closest point. Then switch to the other list, starting from the closest point you go clockwise through the other contour until it is used up. switch back to the first contour and append the rest of their points. force them into cv2 contour format.
The contours returned from cv:findContours
should have a consistent orientation. Outer contours should be oriented counter-clockwise, inner contours clockwise. This follows directly from the algorithm described in Appendix 1 of Suzuki's and Abe's paper.
The image is scanned line by line from top left to bottom right. When a pixel belonging to a border is found, the border is followed by looking at the neighbours of the first pixel in counter-clockwise order (see step 3.3 in the algorithm), until a non-background pixel is found. This is added to the contour and the search continues from this pixel.
The important thing is that in the first iteration the neighbour which is first looked at depends on whether it is an inner or an outer border. In case of an outer border the right-hand neighbour is visited first; in case of an inner border it is the left-hand neighbour. In the next search step the search starts from the last pixel visited.
Due to the scanning happing from top left to bottom right, on detection of an outer border it is assured that all neighbouring pixels to the left and the top of the border pixel are background pixels. With inner border, it is exactly the opposite, all neighbours to the left and the top are non-background pixels.
In combination with the different starting positions for visiting the neighbouring pixels this results in predictable orientations of the contours.
This algorithm is implemented in the icvFetchContour
function which is used internally by cv:findContour
. From there it is clear that the pixel are added to the contour polygon in the order in which they are visited.
As the documentation for cv::findContours
specifically says that they implemented the algorithm by Suzuki et al. and as in this paper the direction and order for visiting the pixels is explicitely defined, I think one can assume that the orientation is kind of guaranteed.
I believe step 1 and 4 of the Appendix I ( in the [Suzuki85] paper you referenced, "Topological Structural Analysis of Digitized Binary Images by Border Following" ) cover your question per the below:
(1) Select one of the following:
(a) If f i, j = 1 and f i, j - 1 = 0, then decide that the pixel ( i, j ) is the border following starting point of an outer border, increment NBD, and ( i 1, j 1 ) + ( i, j - 1 ).
(b) ...
(2) Depending on the types of the newly found border and ...
(3) From the starting point ( i, j ), follow the detected border ...
(4) If f i, j != 1, then LNBD = | f i, j | and resume the raster scan from the pixel ( i, j + 1 ). The algorithm terminates when the scan reaches the lower right corner of the picture.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With