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


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

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

     处理过程的例子:

    处理结果:


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

    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 }

     

     

  • 相关阅读:
    bzoj1901 Zju2112 Dynamic Rankings
    bzoj3932 [CQOI2015]任务查询系统
    poj2104 K-th Number
    splay模板整理
    bzoj1500 [NOI2005]维修数列
    bzoj3223 Tyvj 1729 文艺平衡树
    bzoj1503 [NOI2004]郁闷的出纳员
    bzoj3224 Tyvj 1728 普通平衡树
    用CSS截断字符串
    发布一款仿天猫产品放大镜JQuery插件
  • 原文地址:https://www.cnblogs.com/wjy-lulu/p/7152394.html
Copyright © 2020-2023  润新知