CV计算机视觉

Opencv轮廓检测findContours分析(层次结构)

2017-03-17  本文已影响7271人  东林钟声

Opencv 轮廓检测相关api文档

官方文档相关api

Finds contours in a binary image.

在二值图像中找到轮廓

C++: void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())
C++: void findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point())

parameters:

翻译完了官方文档真不太知道什么意思,特别是什么层次结构,说的简直有毒。跑例子看一下。

还有一个相关的api

Draws contours outlines or filled contours.

画轮廓

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

Parameters:
image – Destination image.
contours – All the input contours. Each contour is stored as a point vector.
contourIdx – Parameter indicating a contour to draw. If it is negative, all the contours are drawn.
color – Color of the contours.
thickness – Thickness of lines the contours are drawn with. If it is negative (for example, thickness=CV_FILLED ), the contour interiors are drawn.
lineType – Line connectivity. See line() for details.
hierarchy – Optional information about hierarchy. It is only needed if you want to draw only some of the contours (see maxLevel ).
maxLevel – Maximal level for drawn contours. If it is 0, only the specified contour is drawn. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This parameter is only taken into account when there is hierarchy available.
offset – Optional contour shift parameter. Shift all the drawn contours by the specified \texttt{offset}=(dx,dy) .
contour – Pointer to the first contour.
externalColor – Color of external contours.
holeColor – Color of internal contours (holes).大概解释在这里,没什么好翻译的。

现在开始分析层次结构,直接看他的描述有毒

从官方代码开始

#include "cv.h"
#include "highgui.h"

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    Mat src;
    // the first command-line parameter must be a filename of the binary
    // (black-n-white) image
    if( argc != 2 || !(src=imread(argv[1], 0)).data)
        return -1;

    Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);

    src = src > 1;
    namedWindow( "Source", 1 );
    imshow( "Source", src );

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    findContours( src, contours, hierarchy,
        CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    // iterate through all the top-level contours,
    // draw each connected component with its own random color
    int idx = 0;
    for( ; idx >= 0; idx = hierarchy[idx][0] )
    {
        Scalar color( rand()&255, rand()&255, rand()&255 );
        drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );
    }

    namedWindow( "Components", 1 );
    imshow( "Components", dst );
    waitKey(0);
}

程序很简单,其能够达到的效果是将连通的部分用随机颜色填充。

效果图如下

填充效果

确实将分别连通的两个部分填充,很神奇,肯定是用到了那个层次结构,对层次结构进行分析。

那么我先讲检测到的所有轮廓分别用不同颜色画出来。代码很简单,就是不停在两点之间画线。

    for (size_t i = 0; i < contours[0].size(); i++)
    {
        line(dst, contours[0][i], contours[0][(i + 1) % contours[0].size()], Scalar(0, 255, 0), 1, 8);
    }
    for (size_t i = 0; i < contours[1].size(); i++)
    {
        line(dst, contours[1][i], contours[1][(i + 1) % contours[1].size()], Scalar(0, 0, 255), 1, 8);
    }

    for (size_t i = 0; i < contours[2].size(); i++)
    {
        line(dst, contours[2][i], contours[2][(i + 1) % contours[2].size()], Scalar(255, 0, 0), 1, 8);
    }
    for (size_t i = 0; i < contours[3].size(); i++)
    {
        line(dst, contours[3][i], contours[3][(i + 1) % contours[3].size()], Scalar(255, 255, 255), 1, 8);
    }

由于之前调试就知道检测出来了4条,所以这里才这样写简单些。
结果图

各个轮廓

这个颜色记住,后面分析有用。

现在开始再重新看之前的层次的定义。

hierarchy[i][0] hiearchy[i][1] , hiearchy[i][2] , and hiearchy[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.
这里主要有两个概念,或者说两个层次,一个是直接上一个下一个,好有一个是父轮廓和子轮廓,很神奇,但是好像有点那个意思了,有嵌套的感觉。再继续分析。把变量都拿出来分析。

contours hierarchy

可以看到0轮廓的下一条轮廓是2轮廓,2轮廓的下一条-1表示没有了。
同时2轮廓的上一条是0,0轮廓的上一条是-1表示没有。所以这就是最外层的轮廓。

再分析,0轮廓的子轮廓是1轮廓,1轮廓的父轮廓当然是0轮廓,再看图


各个轮廓

0、1轮廓分别是绿色和红色,确实有明显的包含关系。到这里就很清楚了。

相当于一个树形结构,上一条下一条针对同一个级别的轮廓,父子轮廓就表示洞类似的结构。

之前源程序的填充方法也可以很简单的想处理,判断是否是父子轮廓之间就行。

到这里轮廓检测的基础部分基本完成,主要其实就是层次结构的分析,nested这个描述还是很准确的,嵌套式的。大概如下图所示。

结构
上一篇 下一篇

猜你喜欢

热点阅读