影醉阏轩窗

衣带渐宽终不悔,为伊消得人憔悴。
扩大
缩小

《图像处理实例》 之 操作规则的圆

目标:提取下图中圆的位置、面积、长度

拿到这幅图像,首先肯定进行灰度化,不然后面没办法操作。

接着进行阈值化,把背景和前景区别开来。

然后形态学操作,把小的斑点过滤掉,以免干扰,同时也为了让图像该分离的分离,该结合的结合。

最后又两种方法-->>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系列

posted on 2017-04-27 13:15  影醉阏轩窗  阅读(793)  评论(0编辑  收藏  举报

导航

/* 线条鼠标集合 */ /* 鼠标点击求赞文字特效 */ //带头像评论