opencv(21)---轮廓属性特征以及应用之凹包

凸包

基本概念

凸包(Convex Hull)是一个计算机几何图形学中的概念, 简单来说, 给定二维平面点集, 凸包就是能够将最外层的点连接起来构成的凸多边形, 它能够包含点集中所有的点。物体的凸包检测场应用在物体识别、手势识别及边界检测等领域。

寻找凸包—convexHull()

函数原型

 
  • 1
  • points: 输入的二维点集, 可以填Mat类型或std::vector
  • hull: 函数调用后找到的凸包
  • clockwise: 操作方向标志符, 当为true时, 输出的凸包为顺时针方向, false为逆时针方向(假定坐标系x轴指向右,y轴指向上方)
  • returnPoints: 操作标志符, 默认值true. 当标志符为true时, 函数返回凸包各个点, 否则返回凸包各点的指数, 当输出数组是std::vector时, 此标志被忽略

凹包一- - -点集的凹包

代码

  Mat img(500, 500, CV_8UC3, Scalar::all(0));  //定义绘制图像
        RNG rng;  //定义随机数对象

        while(1)
        {
            char key;
            int count = (unsigned int)rng % 100;  //定义点的个数
            vector<Point> points;  //定义点集
            for(int i=0; i<count; i++)
            {
                Point pt;
                pt.x = rng.uniform(img.cols/4, img.cols*3/4);  //设定点的x范围
                pt.y = rng.uniform(img.rows/4, img.rows*3/4);  //设定点的y范围
                points.push_back(pt);
            }

            //检测凸包
            vector<int> hull;
            convexHull(Mat(points), hull, true);

            img = Scalar::all(0);
            for(int i = 0; i < count; i++ )
                circle(img, points[i], 3, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), CV_FILLED, CV_AA);

            //准备参数
            int hullcount = (int)hull.size(); //凸包的边数
            Point point0 = points[hull[hullcount-1]]; //连接凸包边的坐标点

            //绘制凸包的边
            for(int  i = 0; i < hullcount; i++ )
            {
                Point point = points[hull[i]];
                circle(img, point, 8, Scalar(0, 255, 0), 2, 8);
                line(img, point0, point, Scalar(255, 255, 255), 2, CV_AA);
                point0 = point;
            }

            //显示效果图
            imshow("img", img);

            //按下ESC,Q,或者q,程序退出
            key = (char)waitKey();
            if( key == 27 || key == 'q' || key == 'Q' )
                break;
        }
        return;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

运行结果

凹包二- - -轮廓的凹包

代码

   Mat srcImg = imread("D:\\1\\12.jpg");
        imshow("src", srcImg);
        Mat dstImg2 = srcImg.clone();
        Mat tempImg(srcImg.rows, srcImg.cols, CV_8UC3, Scalar::all(0));  //用于绘制凸包
        Mat dstImg(srcImg.rows, srcImg.cols, CV_8UC3, Scalar::all(0));  //用于绘制轮廓
        cvtColor(srcImg, srcImg, CV_BGR2GRAY);
        threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化

        vector<vector<Point>> contours;
        vector<Vec4i> hierarcy;

        findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        vector<vector<Point>> hull(contours.size());
        //凸包是对每个轮廓来进行的
        for(int i=0; i<contours.size(); i++)
        {
            convexHull(Mat(contours[i]), hull[i], true);     //查找凸包
        }
        for(int i=0; i<contours.size(); i++)
        {
            drawContours(dstImg, contours, i, Scalar(255, 255, 255), -1, 8);  //绘制轮廓
            //drawContours(dstImg, hull, i, Scalar(rand()%255, rand()%255, rand()%255), 2, 8);
            drawContours(tempImg, hull, i, Scalar(255, 255, 255), -1, 8);
        }
        imshow("hull", tempImg);
        imshow("contours", dstImg);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

运行结果

原图

轮廓

凹包

凸包与轮廓

二者是不同的两个概念,可以利用二者的差,寻找工件的瑕疵区域

 Mat srcImg = imread("D:\\1\\10.png");
    imshow("src", srcImg);
    Mat dstImg2 = srcImg.clone();
    Mat tempImg(srcImg.rows, srcImg.cols, CV_8UC3, Scalar::all(0));  //用于绘制凸包
    Mat dstImg(srcImg.rows, srcImg.cols, CV_8UC3, Scalar::all(0));  //用于绘制轮廓
    cvtColor(srcImg, srcImg, CV_BGR2GRAY);
    threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化

    vector<vector<Point>> contours;
    vector<Vec4i> hierarcy;

    findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    vector<vector<Point>> hull(contours.size());
    //凸包是对每个轮廓来进行的
    for(int i=0; i<contours.size(); i++)
    {
        convexHull(Mat(contours[i]), hull[i], true);     //查找凸包
    }
    for(int i=0; i<contours.size(); i++)
    {
        drawContours(dstImg, contours, i, Scalar(255, 255, 255), -1, 8);  //绘制轮廓
        //drawContours(dstImg, hull, i, Scalar(rand()%255, rand()%255, rand()%255), 2, 8);
        drawContours(tempImg, hull, i, Scalar(255, 255, 255), -1, 8);
    }
    imshow("hull", tempImg);
    imshow("contours", dstImg);


    Mat diffImg;
    absdiff(tempImg, dstImg, diffImg);  //图像相减
    //通过对图像进行腐蚀,来去除边缘的一些区域
    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
    erode(diffImg, diffImg, element);
    imshow("diff", diffImg);

    vector<vector<Point>> contours2;
    vector<Vec4i> hierarcy2;
    cvtColor(diffImg, diffImg, CV_BGR2GRAY); //转为灰度图
    threshold(diffImg, diffImg, 100, 255, CV_THRESH_BINARY); //二值化

    findContours(diffImg, contours2, hierarcy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    drawContours(dstImg2, contours2, -1, Scalar(0, 0, 255), 2, 8);  //红色绘制缺陷轮廓
    imshow("defects", dstImg2);
    waitKey(0);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

运行结果

凸包缺陷分析—convexityDefects()

函数原型

  • contour: 表示输入参数检测到的轮廓, 可以用findContours函数获得
  • convexhull: 输入参数表示检测到的凸包, 可以用convexHull函数获得
  • convexityDefects: 检测到的最终结果, 应为vector
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值