opencv findContours()轮廓特征分析大全(求面积、周长、几何矩、质心、凸包、最小外接矩形、最小外接三角形、最小外接椭圆等)

前言

二值化轮廓发现之后,下一步最主要的就是轮廓特征分析了,常见的特征有:
轮廓面积
轮廓周长
轮廓几何矩、质心
轮廓的最大外接矩形
轮廓的凸包
轮廓的最小外接矩形
轮廓的最小外接三角形
轮廓的最小外接椭圆
轮廓的多边形逼近
轮廓的最小外接圆

一、效果

轮廓几何矩的质心

在这里插入图片描述

轮廓的最大外接矩形

在这里插入图片描述

轮廓的凸包

在这里插入图片描述

轮廓的最小外接矩形

在这里插入图片描述

轮廓的最小外接三角形

在这里插入图片描述

轮廓的最小外接椭圆

在这里插入图片描述

轮廓的多边形逼近
在这里插入图片描述

轮廓的最小外接圆
在这里插入图片描述
轮廓面积和轮廓周长:
在这里插入图片描述

二、opencv对应函数介绍

1.轮廓面积

CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false );

2.轮廓周长

CV_EXPORTS_W double arcLength( InputArray curve, bool closed );

3.轮廓几何矩

CV_EXPORTS_W Moments moments( InputArray array, bool binaryImage = false );

4.轮廓的最大外接矩形

CV_EXPORTS_W Rect boundingRect( InputArray array );

5.轮廓的凸包

详细介绍可参考之前文章:https://blog.csdn.net/weixin_44901043/article/details/123242496?spm=1001.2014.3001.5502

CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull,
                              bool clockwise = false, bool returnPoints = true );

6.轮廓的最小外接矩形

CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );

7.轮廓的最小外接三角形

CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle );

8.轮廓的最小外接椭圆

CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );

9.轮廓的多边形逼近

CV_EXPORTS_W void approxPolyDP( InputArray curve,
                                OutputArray approxCurve,
                                double epsilon, bool closed );

10.轮廓的最小外接圆

CV_EXPORTS_W void minEnclosingCircle( InputArray points,
                                      CV_OUT Point2f& center, CV_OUT float& radius );

三、完整代码

void test_contours_feature()
 {
     cv::Mat src;
       src = cv::imread("D:\\QtProject\\Opencv_Example\\contours_feature\\contours_feature.png", cv::IMREAD_GRAYSCALE);
       if (src.empty()) {
           cout << "Cannot load image" << endl;
           return;
       }
       cv::imshow("src", src);


       cv::Mat binary;
       cv::threshold(src, binary, 150, 255, cv::THRESH_BINARY_INV);

       cv::Mat k55 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5), cv::Point(-1, -1));
       cv::morphologyEx(binary, binary, cv::MORPH_OPEN, k55, cv::Point(-1, -1), 1);


       cv::namedWindow("binary",cv::WINDOW_NORMAL);
       cv::imshow("binary", binary);


       std::vector<std::vector<cv::Point> > defectContours;
       std::vector<cv::Vec4i> hierarchyDefect;
       cv::findContours(binary, defectContours, hierarchyDefect, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);

       cv::Mat contours = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));

       cv::Mat drawCenterPos = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
       cv::Mat drawRect = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
       cv::Mat drawHull = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
       cv::Mat drawRotateRect = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
       cv::Mat drawMinEnclosingCircle = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
       cv::Mat drawMinEnclosingTriangle = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));
       cv::Mat drawEllipse = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));

       std::vector<std::vector<cv::Point>> PolyDPs;
       cv::Mat drawPolyDP = cv::Mat(src.size(), CV_8UC3, cv::Scalar(0,0,0));


       std::vector<std::vector<cv::Point> > hull(defectContours.size());
       for (int i = 0; i < defectContours.size(); i++)
       {
           //轮廓 白色
           cv::drawContours(contours, defectContours, i, cv::Scalar(255,255,255), 1);

           //求面积
           double fArea = cv::contourArea(defectContours[i]);
           qDebug()<<QStringLiteral("面积")<<fArea;

           //求周长
           double fLength = cv::arcLength(defectContours[i],true);
           qDebug()<<QStringLiteral("周长")<<fLength;

           //矩求质心 红色
           cv::Moments mu = cv::moments(defectContours[i]);
           cv::Point2d centerPos = cv::Point2d( mu.m10/mu.m00 , mu.m01/mu.m00);
           cv::circle(drawCenterPos, centerPos, 10, cv::Scalar(0, 0, 255));

           //最大外接矩形 蓝色
           cv::Rect rect = cv::boundingRect(defectContours[i]);
           cv::rectangle(drawRect, rect, cv::Scalar(255,0,0));


           //凸包 黄色
           cv::convexHull(cv::Mat(defectContours[i]), hull[i], false);
           cv::drawContours(drawHull, hull, i, cv::Scalar(0,255,255), 1);

           //最小外接矩形 青色
           cv::RotatedRect rotateRect = cv::minAreaRect(defectContours[i]);
           vector<cv::Point2f> boxPts(4);
           rotateRect.points(boxPts.data());

           for (int j = 0; j < 4; j++)
           {
               cv::line(drawRotateRect, boxPts[j], boxPts[(j + 1) % 4], cv::Scalar(128, 128, 0), 1, 8);  //绘制最小外接矩形每条边
           }
           
           //最小外接圆 棕褐色
           cv::Point2f center;
           float fRadius = 0;
           cv::minEnclosingCircle(defectContours[i], center, fRadius);
           cv::circle(drawMinEnclosingCircle, center, fRadius, cv::Scalar(140,180,210),1);

           //最小外界三角形 粉色
           std::vector<cv::Point2f> points;
           cv::minEnclosingTriangle(defectContours[i], points);
           cv::line(drawMinEnclosingTriangle, points[0], points[1], cv::Scalar(193, 182, 255), 1, 8);  //绘制最小外接三角形每条边
           cv::line(drawMinEnclosingTriangle, points[2], points[1], cv::Scalar(193, 182, 255), 1, 8);  //绘制最小外接三角形每条边
           cv::line(drawMinEnclosingTriangle, points[2], points[0], cv::Scalar(193, 182, 255), 1, 8);  //绘制最小外接三角形每条边


           //椭圆 紫罗兰色
           cv::RotatedRect ellipse =  cv::fitEllipse(defectContours[i]);
           cv::ellipse(drawEllipse, ellipse, cv::Scalar(226,43,138));

           //多边形逼近 洋红色
           std::vector<cv::Point> PolyDP;
           //cv::Mat PolyDP ;
           cv::approxPolyDP(defectContours[i],PolyDP, 0.5, true);
           PolyDPs.push_back(PolyDP);
           //cv::drawContours(drawPolyDP, PolyDP, 0, cv::Scalar(23,56,234));
           //drawPolyDP += cv::Mat(PolyDP);
       }

       //画多边形逼近
       for(int j = 0; j < PolyDPs.size(); j++)
       {
           cv::drawContours(drawPolyDP, PolyDPs, j, cv::Scalar(255,0,255),1);
       }


       drawCenterPos += contours;
       drawRect += contours;
       drawHull += contours;
       drawRotateRect += contours;
       drawMinEnclosingCircle += contours;
       drawMinEnclosingTriangle += contours;
       drawEllipse += contours;

       cv::namedWindow("contours",cv::WINDOW_NORMAL);
       cv::imshow("contours", contours);

       cv::namedWindow("drawRect",cv::WINDOW_NORMAL);
       cv::imshow("drawRect", drawRect);

       cv::namedWindow("drawHull",cv::WINDOW_NORMAL);
       cv::imshow("drawHull", drawHull);

       cv::namedWindow("drawRotateRect",cv::WINDOW_NORMAL);
       cv::imshow("drawRotateRect", drawRotateRect);

       cv::namedWindow("drawCenterPos",cv::WINDOW_NORMAL);
       cv::imshow("drawCenterPos", drawCenterPos);

       cv::namedWindow("drawMinEnclosingCircle",cv::WINDOW_NORMAL);
       cv::imshow("drawMinEnclosingCircle", drawMinEnclosingCircle);

       cv::namedWindow("drawMinEnclosingTriangle",cv::WINDOW_NORMAL);
       cv::imshow("drawMinEnclosingTriangle", drawMinEnclosingTriangle);

       cv::namedWindow("drawEllipse",cv::WINDOW_NORMAL);
       cv::imshow("drawEllipse", drawEllipse);

       cv::namedWindow("drawPolyDP",cv::WINDOW_NORMAL);
       cv::imshow("drawPolyDP", drawPolyDP);
 }
  • 3
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值