文章目录
- 前言
- 一、效果
- 二、opencv对应函数介绍
- 1.轮廓面积
- 2.轮廓周长
- 3.轮廓几何矩
- 4.轮廓的最大外接矩形
- 5.轮廓的凸包
- 6.轮廓的最小外接矩形
- 7.轮廓的最小外接三角形
- 8.轮廓的最小外接椭圆
- 9.轮廓的多边形逼近
- 10.轮廓的最小外接圆
- 三、完整代码
前言
二值化轮廓发现之后,下一步最主要的就是轮廓特征分析了,常见的特征有:
轮廓面积
轮廓周长
轮廓几何矩、质心
轮廓的最大外接矩形
轮廓的凸包
轮廓的最小外接矩形
轮廓的最小外接三角形
轮廓的最小外接椭圆
轮廓的多边形逼近
轮廓的最小外接圆
一、效果
轮廓几何矩的质心
轮廓的最大外接矩形
轮廓的凸包
轮廓的最小外接矩形
轮廓的最小外接三角形
轮廓的最小外接椭圆
轮廓的多边形逼近
轮廓的最小外接圆
轮廓面积和轮廓周长:
二、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);}