zoukankan      html  css  js  c++  java
  • 《图像处理实例》 之 操作规则的圆

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

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

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

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

    最后又两种方法-->>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
    ", Area);
    51             printf("circle length : %f
    ", 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系列

  • 相关阅读:
    EF CodeFirst下,当实体结构发生修改怎么更新数据库结构 【常用总结】
    基于 ASP.NET Core 的 EF Core 入门
    autofac 一个接口多个实现的情况
    C#中使用HttpClient来Post数据的内容HttpContent的各种格式
    # 使用HttpClient的post,get 封装
    C# 模拟提交带附件(input type=file)的表单
    C#使用HttpClient上传文件并附带其他参数
    2021年总结一下
    PhpStorm+Xdebug断点调试
    PHP数组排序
  • 原文地址:https://www.cnblogs.com/wjy-lulu/p/6773731.html
Copyright © 2011-2022 走看看