《图像处理实例》 之 精确寻找一个圆

以下是素材照片,就是寻找中间那个圆就可以了,说起来很简单,做起来不那么容易:

代码很简单,主要是预处理,下面会基体说明!

 处理过程的例子:

处理结果:


首先说明一下怎么寻找一个圆?(本来都忘记这篇博文没写完了,还是一个同志发邮件给我才想起来)

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 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值