以下是素材照片,就是寻找中间那个圆就可以了,说起来很简单,做起来不那么容易:
代码很简单,主要是预处理,下面会基体说明!
处理过程的例子:
处理结果:
首先说明一下怎么寻找一个圆?(本来都忘记这篇博文没写完了,还是一个同志发邮件给我才想起来)
A.寻找圆的大方向
预处理好的话,下面哪种方法都可以得到精确的圆!
1.霍夫圆检测
小伙伴们是不是有这种感觉,刚开始用霍夫的时候很兴奋,调调参数就能找到圆,但是随着你要求找的圆越来越复杂,是不是发现霍夫没用了?
真的不是霍夫没用了,是你预处理没做好,看看霍夫的原理(极坐标的转换方式,我另一篇博文有说http://www.cnblogs.com/wjy-lulu/p/6677280.html)
一句话你处理的越好检测的就越好!!
2.拟合圆
利用圆的函数去拟合,当然这里分为两种方案:
a.点在圆的边缘,这个需要圆的函数拟合。
b.点在圆内,这个需要圆的面积+函数拟合。
3.最小外接圆
注意这不是和方法2相同!!这个方法是找到一个圆然后使得圆面积最小且包含所有点,算法实现应该有很多了,我个人认为用k-means寻找质心然后再找最小圆。
4.分水岭算法
这个方法在另一篇博文实现,不在阐述:http://www.cnblogs.com/wjy-lulu/p/7056466.html
B.预处理
--------->>>>>感觉没多大意义,貌似任何算法的基础都是预处理,具体问题具体对待
上代码:
(代码写到一半就没写了,原因不想说了,后面也不想改进了,其实针对具体问题还有很多改进的地方,精确寻找圆不是很困难的事)
1 #include<iostream>
2 #include <opencv2/opencv.hpp>
3 #include <math.h>
4 using namespace cv;
5 using namespace std;
6
7 int Threshold_Value = 176;
8 const int Threshold_Max_value = 255;
9 const int Threshold_type_value = 3;
10
11 Mat input_image, threshold_image, output_image, Middle_image;
12
13 void Threshold_Image_Bar(int, void *);
14
15 int main(int argc, char**argv)
16 {
17 input_image = imread("b.jpg");
18 if (input_image.data == NULL) {
19 return -1; cout << "can't open image.../";
20 }
21 imshow("Sourse Image", input_image);
22 blur(input_image, Middle_image, Size(3, 3), Point(-1, -1), 4);
23 cvtColor(Middle_image, Middle_image, COLOR_RGB2GRAY);
24 const float init_pointx = saturate_cast<float>(Middle_image.cols / 7);
25 const float init_pointy = saturate_cast<float>(Middle_image.rows / 7);
26 Rect roi_rect = Rect(Point2f(2 * init_pointx, 2 * init_pointy), Point2f(6 * init_pointx, 6 * init_pointy));
27 Mat roi_Image = Middle_image(roi_rect);
28 Middle_image = roi_Image;
29 threshold(Middle_image, threshold_image, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
30 Mat kernel_rect = getStructuringElement(MORPH_ELLIPSE, Size(30, 30), Point(-1, -1));
31 Mat kernel_circle = getStructuringElement(MORPH_ELLIPSE, Size(10, 10), Point(-1, -1));
32 morphologyEx(threshold_image, threshold_image, MORPH_CLOSE, kernel_circle);
33 Mat RedImage = threshold_image.clone();
34 morphologyEx(RedImage, threshold_image, MORPH_OPEN, kernel_rect);
35 for (size_t i = 0; i < threshold_image.rows; i++)
36 {
37 for (size_t j = 0; j < threshold_image.cols; j++)
38 {
39 RedImage.at<uchar>(i, j) = saturate_cast<uchar>(RedImage.at<uchar>(i, j) - threshold_image.at<uchar>(i, j));
40 }
41 }
42 vector<vector<Point>> contours;
43 vector<Vec4i> hierarchy;
44 Mat showImage = Mat::zeros(RedImage.size(), CV_8UC1);
45 findContours(RedImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
46 for (size_t i = 0; i < contours.size(); i++)
47 {
48 if (minAreaRect(contours[i]).size.area() > 10000 && minAreaRect(contours[i]).size.height > 80 && minAreaRect(contours[i]).size.width > 80)//这个参数大概就可以
49 {
50 drawContours(showImage, contours, static_cast<int>(i), Scalar(255, 255, 255), 1);
51 }
52 }
53 vector<Point> points;
54 for (int i = 0; i < showImage.rows; i++)
55 {
56 for (int j = 0; j < showImage.cols; j++)
57 {
58 if (showImage.at<uchar>(i, j) == 255)
59 {
60 points.push_back(Point(j, i));
61 }
62 }
63 }
64 Point2f center;
65 float radius;
66 if (points.data() == 0)
67 {
68 printf("Don't detecte point");
69 return -1;
70 }
71 minEnclosingCircle(points, center, radius);
72 center.x += 2 * init_pointx;
73 center.y += 2 * init_pointy;
74 Mat result = Mat::zeros(RedImage.size(), CV_8UC3);
75 circle(input_image, center, radius, Scalar(0, 0, 255), 2);
76 waitKey(0);
77 return 0;
78 }
79 void Threshold_Image_Bar(int, void *)
80 {
81 threshold(Middle_image, threshold_image, 65, 255,THRESH_BINARY_INV);//110,65
82 imshow("Threshold Image", threshold_image);
83 Mat kernel = getStructuringElement(MORPH_RECT, Size(50, 50), Point(-1, -1));
84 Mat RedImage = threshold_image.clone();
85 morphologyEx(RedImage, threshold_image, MORPH_OPEN, kernel);
86 for (size_t i = 0; i < threshold_image.rows; i++)
87 {
88 for (size_t j = 0; j < threshold_image.cols; j++)
89 {
90 RedImage.at<uchar>(i, j) = saturate_cast<uchar>(RedImage.at<uchar>(i, j) - threshold_image.at<uchar>(i, j));
91 }
92 }
93 vector<vector<Point>> contours;
94 vector<Vec4i> hierarchy;
95 Mat showImage = Mat::zeros(RedImage.size(), CV_8UC1);
96 findContours(RedImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
97 for (size_t i = 0; i < contours.size(); i++)
98 {
99 if (boundingRect(contours[i]).area() > 20000)
100 {
101 drawContours(showImage, contours, static_cast<int>(i), Scalar(255, 255, 255), 1);
102 }
103 }
104 vector<Point> points;
105 for (int i = 0; i < showImage.rows; i++)
106 {
107 for (int j = 0; j < showImage.cols; j++)
108 {
109 if (showImage.at<uchar>(i, j) == 255)
110 {
111 points.push_back(Point(j, i));
112 }
113 }
114 }
115 Point2f center;
116 float radius;
117 minEnclosingCircle(points, center, radius);
118 Mat result = Mat::zeros(RedImage.size(), CV_8UC3);
119 circle(input_image, center, radius, Scalar(0, 0, 255), 2);
120 }