问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/45323590/do-contours-returned-by-cvfindcontours-have-a-consistent-orientation