OpenCV | 二值圖像分析的技巧都在這裡[輪廓分析/ 形態學]
OpenCV | 二值圖像分析的技巧都在這裡[輪廓分析/ 形態學]
資料來源: https://mp.weixin.qq.com/s/MGKDtYJd5Yw96SirHZh0Yw
01.輪廓分析相關的常用函數功能列表
–輪廓面積
-輪廓周長
-輪廓幾何矩
-輪廓的最小外接矩形[長方形]
-輪廓的最大外接矩形
-輪廓的最小外接圓
-輪廓的最小外接三角形
-輪廓擬合(支持擬合直線、橢圓、圓)
-輪廓的凸包
-輪廓層次信息提取
-多邊形逼近
-計算歐拉數
02.輪廓分析相關的常用函數原型宣告:
// 计算轮廓面积 double cv::contourArea( InputArray contour, bool oriented = false ) // 计算轮廓周长 double cv::arcLength( InputArray curve, bool closed ) // 计算几何矩与中心距 Moments cv::moments( InputArray array, bool binaryImage = false ) // 计算最小外接矩形 RotatedRect cv::minAreaRect( InputArray points ) // 计算最大外接矩形 Rect cv::boundingRect( InputArray array ) // 计算最小外接圆/拟合圆 void cv::minEnclosingCircle( InputArray points, Point2f & center, float & radius ) // 计算最小外接三角形/拟合三角形 double cv::minEnclosingTriangle( InputArray points, OutputArray triangle ) // 拟合直线 void cv::fitLine( InputArray points, OutputArray line, int distType, double param, double reps, double aeps ) // 拟合椭圆 RotatedRect cv::fitEllipse( InputArray points ) // 计算凸包 void cv::convexHull( InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true ) // 多边形逼近-逼近真实形状 void cv::approxPolyDP( InputArray curve, OutputArray approxCurve, double epsilon, bool closed )
03.這裡再分享一個硬幣計數的例子!
// 加载图像
Mat img = imread("D:/CoinsB.png");
imshow("Original Image", img);
// 阈值化操作
Mat gray, binary;
cvtColor(img, gray, COLOR_BGR2GRAY);
float t = threshold(gray, binary, 0, 255, THRESH_BINARY|THRESH_OTSU);
imshow("binary", binary);
imwrite("D:/binary1.png", binary);
// 形态学操作
Mat se = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(binary, binary, MORPH_OPEN, se, Point(-1, -1));
// 轮廓发现
vector<Vec4i> hireachy;
vector<vector<Point>> contours;
bitwise_not(binary, binary);
findContours(binary, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
Mat result = img.clone();
Point2f center;
float radius;
// 轮廓分析
for (size_t t = 0; t < contours.size(); t++) {
double area = contourArea(contours[t]);
if (area < 1000) {
continue;
}
RotatedRect rrt = fitEllipse(contours[t]);
radius = min(rrt.size.width, rrt.size.height)/2.0;
circle(result, rrt.center, radius, Scalar(0, 0, 255), 4, 8, 0);
Moments mm = moments(contours[t]);
double cx = mm.m10 / mm.m00;
double cy = mm.m01 / mm.m00;
circle(result, Point(cx, cy), 2, Scalar(255, 0, 0), 2, 8, 0);
}
// 显示结果
imshow("result", result);
imwrite("D:/drawing.png", result);
waitKey(0);