天天看點

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]

---

繼續閱讀