精确寻找一个圆(接的一个小外包)
Posted 寂寞的小乞丐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了精确寻找一个圆(接的一个小外包)相关的知识,希望对你有一定的参考价值。
以下是素材照片,就是寻找中间那个圆就可以了,说起来很简单,做起来不那么容易:
代码很简单,主要是预处理,下面会基体说明!
处理过程的例子:
处理结果:
首先说明一下怎么寻找一个圆?(本来都忘记这篇博文没写完了,还是一个同志发邮件给我才想起来)
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 }
以上是关于精确寻找一个圆(接的一个小外包)的主要内容,如果未能解决你的问题,请参考以下文章