OpenCV的findContours源码与原理

1、源码


https://github.com/opencv/opencv/blob/master/modules/imgproc/src/contours.cpp


\opencv\build\include\opencv2\imgproc\imgproc.hpp

/** @brief Finds contours in a binary image.
The function retrieves contours from the binary image using the algorithm @cite Suzuki85 . The contours
are a useful tool for shape analysis and object detection and recognition. See squares.cpp in the
OpenCV sample directory.
@note Since opencv 3.2 source image is not modified by this function.
@param image Source, an 8-bit single-channel image. Non-zero pixels are treated as 1's. Zero
pixels remain 0's, so the image is treated as binary . You can use #compare, #inRange, #threshold ,
#adaptiveThreshold, #Canny, and others to create a binary image out of a grayscale or color one.
If mode equals to #RETR_CCOMP or #RETR_FLOODFILL, the input can also be a 32-bit integer image of labels (CV_32SC1).
@param contours Detected contours. Each contour is stored as a vector of points (e.g.
std::vector<std::vector<cv::Point> >).
@param hierarchy Optional output vector (e.g. std::vector<cv::Vec4i>), containing information about the image topology. It has
as many elements as the number of contours. For each i-th contour contours[i], the elements
hierarchy[i][0] , hierarchy[i][1] , hierarchy[i][2] , and hierarchy[i][3] are set to 0-based indices
in contours of the next and previous contours at the same hierarchical level, the first child
contour and the parent contour, respectively. If for the contour i there are no next, previous,
parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.
@param mode Contour retrieval mode, see #RetrievalModes
@param method Contour approximation method, see #ContourApproximationModes
@param offset Optional offset by which every contour point is shifted. This is useful if the
contours are extracted from the image ROI and then they should be analyzed in the whole image
context.
 */
CV_EXPORTS_W void findContours( InputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset = Point());
/** @overload */
CV_EXPORTS void findContours( InputArray image, OutputArrayOfArrays contours,
                              int mode, int method, Point offset = Point());


2、论文


根据opencv官方文档,OpenCV: Contours Hierarchy,采用的是:


Suzuki, S. and Abe, K.,Topological Structural Analysis of Digitized Binary Images by Border Following. CVGIP 30 1, pp 32-46 (1985)


说明:openCv的contours是分级的,其寻边理论依据(方式)参考suzuki的论文《Topological structural analysis of digitized binary images by border following》。


http://pdf-s3.xuebalib.com:1262/1ftg5E69C3uX.pdf


3、Contour 的寻边模式 Mode

openCV通过一个矩阵来管理等级,矩阵的元素表示方法是:[Next, Previous, First_Child, Parent]


OpenCV的findContours源码与原理


RETR_LIST:列出所有的边,没有父子层级之分(全部边缘都为1级)。

在这种模式下,这8条边建立的等级关系为

[ 1, -1, -1, -1], [ 2, 0, -1, -1],  [ 3, 1, -1, -1],  [ 4, 2, -1, -1],  

[ 5, 3, -1, -1], [ 6, 4, -1, -1], [ 7, 5, -1, -1], [-1, 6, -1, -1]

例如边“0”,其同等级的Next是边“1”,前一个不存在(-1),没有First_Child, Parent,这两个参数也都设为-1,所以第0个元素是

[1,-1,-1,-1];边“1”,其同等级的Next是边“2”,前一个边是“0”,没有First_Child, Parent,两个-1,所以第1个元素是[2,0,-1,-1];依次类推。


RETR_EXTERNAL:列出最外面的边(如物体的外边框),不管被包围的内环或边(如物体的孔洞)。


RETR_CCOMP:只取2个层级的边,如下图,只把边(粉红色)分为两个层(绿色),标记为绿色的(1)顶层和(2)次层。

OpenCV的findContours源码与原理



上面图中,这9条边建立的等级关系为

[ 3, -1, 1, -1],    [ 2, -1, -1, 0],    [-1, 1, -1, 0],    [ 5, 0, 4, -1],    [-1, -1, -1, 3],

[ 7, 3, 6, -1],    [-1, -1, -1, 5],    [ 8, 5, -1, -1],    [-1, 7, -1, -1]

例如第"0"边,其相邻的Next是边"3", Previous不存在(-1),First-child=边"1",Parent不存在(-1),所以其相应的元素为

[3, -1, 1, -1],其余元素依此规则类推。


RETR_TREE:返回所有的边及层级关系,


OpenCV的findContours源码与原理


这9条边建立的等级关系为

[ 7, -1, 1, -1],    [-1, -1, 2, 0],    [-1, -1, 3, 1],    [-1, -1, 4, 2],    [-1, -1, 5, 3],

[ 6, -1, -1, 4],    [-1, 5, -1, 4],    [ 8, 0, -1, -1],   [-1, 7, -1, -1]


---



上一篇:从包工头到程序猿(一)输红了眼


下一篇:为创业我做了十年的程序员,你告诉我“程序员不适合创业”?!