OpenCV之图像处理(二十九) 轮廓发现(find contour)

轮廓:就是图像上某一部分与其他不一样的部分的边界

轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法。所以边缘提取的阈值选定会影响最终轮廓发现结果

拓扑:就是把实体抽象成与其大小、形状无关的“点”,而把连接实体的线路抽象成“线”,进而以图的形式来表示这些点与线之间关系的方法,
        其目的在于研究这些点、线之间的相连关系。表示点和线之间关系的图被称为拓扑结构图。

findContours( // 在二值图像上发现轮廓
    InputOutputArray  binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit。  findContours 会改动输入图像 binImg 中元素的值?
    OutputArrayOfArrays  contours,//  全部发现的轮廓对象
    OutputArray hierachy, // 图像的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。  发现的层次
    int mode, //  mode轮廓检索模式,可以通过cv::RetrievalModes()查看详细信息
                        RETR_EXTERNAL:表示只检测最外层轮廓,对所有轮廓设置hierarchy[i][2]=hierarchy[i][3]=-1 
                        RETR_LIST:提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系 
                        RETR_CCOMP:提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),顶层为连通域的外围边界,次层位内层边界 
                        RETR_TREE:提取所有轮廓并重新建立网状轮廓结构 
                        RETR_FLOODFILL:官网没有介绍,应该是洪水填充法 
    int method,// method:轮廓近似方法可以通过cv::ContourApproximationModes()查看详细信息 
                        CHAIN_APPROX_NONE:获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1 
                        CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,值保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息 
                        CHAIN_APPROX_TC89_L1和CHAIN_APPROX_TC89_KCOS使用Teh-Chinl链逼近算法中的一种 
    Point offset=Point()//  轮廓像素的位移,默认(0, 0)没有位移
)

drawContours( // 绘制轮廓,一次只能根据轮廓索引号绘制一次,需要循环所有发现的轮廓
    InputOutputArray  binImg, // 输出图像
    OutputArrayOfArrays  contours,//  全部发现的轮廓对象
    Int contourIdx// 轮廓索引号
    const Scalar & color,// 绘制时候颜色
    int  thickness,// 绘制线宽,如果传 -1 表示填充轮廓
    int  lineType ,// 线的类型LINE_8
    InputArray hierarchy,// 拓扑结构图,   发现的层次
    int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓
    Point offset=Point()// 轮廓位移,可选
)

代码

    #include "../common/common.hpp"

    static Mat src, dst;
    static const char* title = "findcontours";
    static int threshold_value = 100;
    static int threshold_max = 255;
    static RNG rng;

    static void contours(int, void*);

    void main(int argc, char** argv)
    {
        src = imread(getCVImagesPath("images/happyfish.png"), IMREAD_COLOR);
        imshow("happyfish", src);
        cvtColor(src, src, CV_BGR2GRAY);

        namedWindow(title, CV_WINDOW_AUTOSIZE);
        createTrackbar("threshold:", title, &threshold_value, threshold_max, contours);
        contours(0, 0);

        waitKey(0);
    }

    void contours(int, void*)
    {
        Mat canny_output;
        vector<vector<Point>> contours;//每个轮廓由一系列点组成
        vector<Vec4i> hierachy;
        //提取边缘
        Canny(src, canny_output, threshold_value, threshold_value * 2, 3, false);
        printf("%d\n", hierachy.size());//0 。。 需要设置hierachy 才会由值?
        //发现轮廓
        findContours(canny_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

        //绘制轮廓
        //因为要用不同颜色区分轮廓,所以这里用的CV_8UC3 3通道彩色图,如果是CV_8UC1 绘制的就是灰度图,感官上不好区分
        dst = Mat::zeros(src.size(), CV_8UC3);
        RNG rng(12345);
        for (size_t i = 0; i < contours.size(); i++) {
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//随机颜色
            drawContours(dst, contours, i, color, 2, 8, hierachy, 0, Point(0, 0));//颜色一致的就属同一发现的轮廓
        }
        imshow(title, dst);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81182562
今日推荐