《图像处理实例》 之 操作规则的圆
目标:提取下图中圆的位置、面积、长度
拿到这幅图像,首先肯定进行灰度化,不然后面没办法操作。
接着进行阈值化,把背景和前景区别开来。
然后形态学操作,把小的斑点过滤掉,以免干扰,同时也为了让图像该分离的分离,该结合的结合。
最后又两种方法-->>1.霍夫变换求圆。2.边缘函数求圆。
二值化:
形态学操作:
下面是进行基于边缘检测函数的方法--->>>>
手动计算的圆心、面积、周长:
自带函数计算的结果:
对比手动计算和库函数计算的结果,操作还是比较满意的,看上图画的圆已经和实际基本重合。
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include <opencv2/opencv.hpp> 4 #include <math.h> 5 using namespace cv; 6 using namespace std; 7 8 RNG rng(12345); 9 10 Mat input_image, threshold_image, output_image, Middle_image; 11 12 13 int main(int argc, char**argv) 14 { 15 input_image = imread("1.jpg"); 16 if (input_image.data == NULL) { 17 return -1; cout << "can't open image.../"; 18 } 19 imshow("Sourse Image", input_image); 20 cvtColor(input_image, Middle_image,COLOR_RGB2GRAY); 21 //imshow("Gray Image", Middle_image); 22 threshold(Middle_image, Middle_image,0,255, THRESH_BINARY_INV| THRESH_OTSU); 23 imshow("Threshold Image", Middle_image); 24 Mat kernel = getStructuringElement(MORPH_RECT,Size(7,7),Point(-1,-1)); 25 //------------------------------清除小的杂质------------------------------// 26 morphologyEx(Middle_image, Middle_image, MORPH_CLOSE,kernel,Point(-1,-1)); 27 //-------------连接小的区域为下面做准备,其实不操作这步也是可以的---------// 28 morphologyEx(Middle_image, Middle_image, MORPH_OPEN, kernel, Point(-1, -1)); 29 imshow("morphology_Open Image", Middle_image); 30 vector<vector<Point>> contours; 31 vector<Vec4i> hierarchy; 32 findContours(Middle_image,contours,hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); 33 Mat show_image = Mat::zeros(input_image.size(),input_image.type()); 34 for (size_t i = 0; i < contours.size(); i++) 35 { 36 //------清除太大和太小的区域--------// 37 double Area = contourArea(contours[i]); 38 if (Area > 100000) continue; 39 if (Area < 10000) continue; 40 //double length = arcLength(contours[i],1); 41 //if (length < 500) continue; 42 Rect temp = boundingRect(contours[i]); 43 //------------特殊方法求圆-----------// 44 float roti = (temp.width) / (temp.height); 45 if (roti > 0.9&&roti < 1.1) 46 { 47 drawContours(show_image, contours, static_cast<int>(i), Scalar(255, 0, 0), 2); 48 int x = temp.x + temp.width / 2; 49 int y = temp.y + temp.width / 2; 50 printf("circle area : %f\n", Area); 51 printf("circle length : %f\n", arcLength(contours[i], 0)); 52 //---------------手动计算圆位置、面积、长度----------// 53 double WJY_Area = CV_PI*temp.width/2*temp.width/2; 54 double WJY_Length = 2 * CV_PI*temp.width/2; 55 char str_wjy_Area[15], str_wjy_Length[15]; 56 sprintf(str_wjy_Area, "Area:%3f", abs(WJY_Area));//把int--->>>String 57 sprintf(str_wjy_Length, "Length:%3f", abs(WJY_Length)); 58 putText(show_image, str_wjy_Area, Point(x-30, y), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(200, 100, 100), 2, 16); 59 putText(show_image, str_wjy_Length, Point(x - 30, y-30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(200, 100, 100), 2, 16); 60 circle(show_image,Point(x,y), temp.width / 2,Scalar(0,0,255),2, LINE_AA);//自己计算的圆 61 circle(show_image, Point(x, y), 2, Scalar(0, 0, 255), 2, LINE_AA);//圆心 62 } 63 } 64 //------过滤小的片段,因为上面用了长度和面积都没过滤掉-------// 65 //threshold(Middle_image, Middle_image, 200, 255, 0); 66 imshow("FindContours Image", Middle_image); 67 imshow("WJY_Image", show_image); 68 69 waitKey(0); 70 return 0; 71 }
--->>>下面进行霍夫变换的方法--->>>
下面是经过很多次的参数调节得到的图:
当HoughCircles(Middle_image, circles, HOUGH_GRADIENT,1.5, 10, 200, 50);
下图所示:
不仅效果不好,而且很难调节参数,我认为是我调节最好的了,而且前期也是经过形态学过滤,
==》》最可笑的是opencv官网对霍夫圆检测的一句话:
Usually the function detects the centers of circles well. However, it may fail to find correct radii. You can assist to the function by specifying the radius range ( minRadius and maxRadius ) if you know it. Or, you may ignore the returned radius, use only the center, and find the correct radius using an additional procedure。
大概意思就是,大部分情况检测的不好,要通过其它手段进行辅助,最好只是检测圆心。。。
注意:我想通过边缘检测对霍夫圆进行辅助操作,没想到这个API只能输入灰度图,二值图不能进行输入。。。爱莫能助
上一下代码:
1 int main(int argc, char**argv) 2 { 3 input_image = imread("2.jpg"); 4 if (input_image.data == NULL) { 5 return -1; cout << "can't open image.../"; 6 } 7 imshow("Sourse Image", input_image); 8 cvtColor(input_image, Middle_image, COLOR_RGB2GRAY); 9 imshow("Gray Image", Middle_image); 10 11 Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1)); 12 //------------------------------清除小的杂质------------------------------// 13 morphologyEx(Middle_image, Middle_image, MORPH_CLOSE, kernel, Point(-1, -1)); 14 //-------------连接小的区域为下面做准备,其实不操作这步也是可以的---------// 15 morphologyEx(Middle_image, Middle_image, MORPH_OPEN, kernel, Point(-1, -1)); 16 imshow("morphology_Open Image", Middle_image); 17 vector<Vec3f> circles; 18 HoughCircles(Middle_image, circles, HOUGH_GRADIENT, 19 1.5, 10, 200, 50); 20 cvtColor(Middle_image, Middle_image, COLOR_GRAY2BGR); 21 Mat show_image1 = Mat::zeros(input_image.size(), input_image.type()); 22 for (size_t i = 0; i < circles.size(); i++) 23 { 24 Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); 25 int radius = cvRound(circles[i][2]); 26 // draw the circle center 27 circle(Middle_image, center, 3, Scalar(0, 0, 255), -1, 8, 0); 28 // draw the circle outline 29 circle(Middle_image, center, radius, Scalar(0, 0, 255), 3, 8, 0); 30 } 31 imshow("HoughCircle Image", Middle_image); 32 waitKey(0); 33 return 0; 34 }
参考:贾老师opencv系列
-------------------------------------------
个性签名:衣带渐宽终不悔,为伊消得人憔悴!
如果觉得这篇文章对你有小小的帮助的话,记得关注再下的公众号,同时在右下角点个“推荐”哦,博主在此感谢!