zoukankan      html  css  js  c++  java
  • OpenCV图像处理中“找圆技术”的使用


    一、为什么“找圆”
        圆是基本图形的一种,更为重要的是,自然情况下采集的图像,很少大量存在“圆”;但凡存在的,大都是人工的,那么就必然代表特定的意义,从而方便定位、分割和识别。
        OpenCV现有代码中能够直接“找圆”,主要有2个,一个是“HoughCircle ”,另一个是“BlobDetector ”,此外基本的轮廓分析也能够用于圆的寻找。但是这些基础的方法,涉及到的参数比较多,一方面我们需要深入理解、一方面需要融合运用,才能够有效提高识别准确率。因此结合实践,整理相关内容如下:
    1. “找圆”在图像处理中的价值和应用案例;
    2. 深入理解“HoughCircle ”的参数设置和优缺点;
    3. 深入理解 “BlobDetector”的参数设置和应用实践;
    4. 进一步理解”阈值-轮廓-分割“的分割方法和在“找圆”上的运用;
    5. 融合目前技术,提出”找圆算法链“,提高识别准确率。
    6. 对圆度、凸性、惯性比等基础知识的进一步认识。
    希望能够为图像处理工程师、爱好者提供一些启发。
    二、有效“找圆”的方法
    OpenCV现有代码中,设计“找圆”算法的,主要有2个,一个是“HoughCircle ”,另一个是“BlobDetector ”,此外基本的轮廓分析也能够用于圆的寻找。
     2.1HoughCircle  霍夫圆变换

      

    代码: 

    #include <opencv2/imgproc.hpp>
    #include <opencv2/highgui.hpp>
    #include <math.h>
    using namespace cv;
    using namespace std;
    int main(int argc, char** argv)
    {
        Mat img, gray;
        if( argc != 2 || !(img=imread(argv[1], 1)).data)
            return -1;
        cvtColor(img, gray, COLOR_BGR2GRAY);
        // smooth it, otherwise a lot of false circles may be detected
        GaussianBlur( gray, gray, Size(99), 22 );
        vector<Vec3f> circles;
        HoughCircles(gray, circles, HOUGH_GRADIENT,2, gray.rows/4200100 );
        for( size_t i = 0; i < circles.size(); i++ )
        {
             Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
             int radius = cvRound(circles[i][2]);
             // draw the circle center
             circle( img, center, 3, Scalar(0,255,0), -180 );
             // draw the circle outline
             circle( img, center, radius, Scalar(0,0,255), 380 );
        }
        namedWindow( "circles"1 );
        imshow( "circles", img );
        waitKey(0);
        return 0;
    }

    特别需要注意的是,目前版本出现新参数“HOUGH_GRADIENT_ALT”,在默认参数下比以前有很大程度的精度提升:

    file

    但是HoughCircle的缺点也是显而易见的,简单来说,在默认参数下,它非常容易丢目标。

    2.2BlobDetector 

    所谓Blob就是图像中一组具有某些共同属性(例如,灰度值)的连接像素。OpenCV提供了一种方便的方法来检测斑点并根据不同的特征对其进行过滤。

    // Setup SimpleBlobDetector parameters.
    SimpleBlobDetector::Params params;
    // Change thresholds
    params.minThreshold = 10;
    params.maxThreshold = 200;
    // Filter by Area.
    params.filterByArea = true;
    params.minArea = 1500;
    // Filter by Circularity
    params.filterByCircularity = true;
    params.minCircularity = 0.1;
    // Filter by Convexity
    params.filterByConvexity = true;
    params.minConvexity = 0.87;
    // Filter by Inertia
    params.filterByInertia = true;
    params.minInertiaRatio = 0.01;
    #if CV_MAJOR_VERSION < 3   // If you are using OpenCV 2
      // Set up detector with params
      SimpleBlobDetector detector(params);
      // You can use the detector this way
      // detector.detect( im, keypoints);
    #else
     
            // Set up detector with params
            cv::Ptr<cv::SimpleBlobDetectordetector = cv::SimpleBlobDetector::create(params);
            vector<KeyPointkeypoints;
            detector->detect(screw1keypoints);  
    #endif

    在OpenCV中实现的叫做SimpleBlobDetector,它基于以下描述的相当简单的算法,并且进一步由参数控制,具有以下步骤。

    SimpleBlobDetector::Params::Params()
    {
        thresholdStep = 10;    //二值化的阈值步长,即公式1的t
        minThreshold = 50;   //二值化的起始阈值,即公式1的T1
        maxThreshold = 220;    //二值化的终止阈值,即公式1的T2
        //重复的最小次数,只有属于灰度图像斑点的那些二值图像斑点数量大于该值时,该灰度图像斑点才被认为是特征点
        minRepeatability = 2;   
        //最小的斑点距离,不同二值图像的斑点间距离小于该值时,被认为是同一个位置的斑点,否则是不同位置上的斑点
        minDistBetweenBlobs = 10;
     
        filterByColor = true;    //斑点颜色的限制变量
        blobColor = 0;    //表示只提取黑色斑点;如果该变量为255,表示只提取白色斑点
     
        filterByArea = true;    //斑点面积的限制变量
        minArea = 25;    //斑点的最小面积
        maxArea = 5000;    //斑点的最大面积
     
        filterByCircularity = false;    //斑点圆度的限制变量,默认是不限制
        minCircularity = 0.8f;    //斑点的最小圆度
        //斑点的最大圆度,所能表示的float类型的最大值
        maxCircularity = std::numeric_limits<float>::max();
     
        filterByInertia = true;    //斑点惯性率的限制变量
        minInertiaRatio = 0.1f;    //斑点的最小惯性率
        maxInertiaRatio = std::numeric_limits<float>::max();    //斑点的最大惯性率
     
        filterByConvexity = true;    //斑点凸度的限制变量
        minConvexity = 0.95f;    //斑点的最小凸度
        maxConvexity = std::numeric_limits<float>::max();    //斑点的最大凸度
    }

    • 阈值:通过使用以minThreshold开始的阈值对源图像进行阈值处理,将源图像转换为多个二进制图像。这些阈值以thresholdStep递增,直到maxThreshold。因此,第一个阈值为minThreshold,第二个阈值为minThreshold + thresholdStep,第三个阈值为minThreshold + 2 x thresholdStep,依此类推;
    • 分组:在每个二进制图像中,连接的白色像素被分组在一起。我们称这些二进制blob;
    • 合并:计算二进制图像中二进制斑点的中心,并合并比minDistBetweenBlob更近的斑点;
    • 中心和半径计算:计算并返回新合并的Blob的中心和半径。

    并且可以进一步设置SimpleBlobDetector的参数来过滤所需的Blob类型。

    • 按颜色:首先需要设置filterByColor =True。设置blobColor = 0可选择较暗的blob,blobColor = 255可以选择较浅的blob。
    • 按大小:可以通过设置参数filterByArea = 1以及minArea和maxArea的适当值来基于大小过滤blob。例如。设置minArea = 100将滤除所有少于100个像素的斑点。
    • 圆度:这只是测量斑点距圆的距离。例如。正六边形的圆度比正方形高。要按圆度过滤,请设置filterByCircularity =1。然后为minCircularity和maxCircularity设置适当的值。圆度定义为()。圆的为圆度为1,正方形的圆度为PI/4,依此类推。
    • 按凸性:凸度定义为(斑点的面积/凸包的面积)。现在,形状的“凸包”是最紧密的凸形,它完全包围了该形状,用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。直观感受上,凸性越高则里面“奇怪的部分”少。要按凸度过滤,需设置filterByConvexity = true,minConvexity、maxConvexity应该属于[0,1],而且maxConvexity> minConvexity。
    • 按惯性比:这个词汇比较抽象。我们需要知道Ratio可以衡量形状的伸长程度。简单来说。对于圆,此值是1,对于椭圆,它在0到1之间,对于直线,它是0。按惯性比过滤,设置filterByInertia = true,并设置minInertiaRatio、maxInertiaRatio同样属于[0,1]并且maxConvexity> minConvexity。
      按凸性(左低右高)按惯性比(左低右高)
      Concave versus Convex Shape Inertia Ratio

    这里的基础知识可能比较复杂,关键是默认参数下,识别的效果应该说出奇的好。
    cv::Ptr<cv::SimpleBlobDetector> detector = cv::SimpleBlobDetector::create();

    但是存在的主要问题是由于blob分析的配置参数太多,优化起来存在困难。同时对于某些情况,明显识别错误。

    2.3 基本轮廓分析
    更普通的情况下,我们还是需要从轮廓分析开始,通过上面提出的“圆度”来寻找圆,主要是用来“查漏补缺”,或者是用于特殊情况的查找。

    三、算法融合、协作增效
    在前面已经详细分析3种主要算法的基础上,本文的重点创造一个“算法链”找到的目标有效地融合起来,并且进一步横向分析研究算法间的关系,希望多少能够给关注这个方向、有类似需求的创作者一些思考。
    算法流程
    首先对于自然图片,通过blod detection获得准确的半径;而后基于准确的半径,分别调用HoughCircle以查漏补缺;最后,以上获得的结果,需要进行融合筛选。这个方法,我在“钢管识别”项目上得到了突出的成功应用,最终能够实现非常高的准确识别。主要是基于以下几点:
    1、blobdetector能够找到准确的圆的半径,但是会找错、找漏;
    2、HoughCircle在有“准确的圆的半径”的加持下,能够很大程度上提高准确识别效率;
    3、目标物体是有“固有特征”的,比如这里需要寻找的钢管,他们的“半径”基本上是一致的。

    如果对于这个项目感兴趣,可以在51cto课程上搜索,感谢阅读至此,希望有所帮助。





  • 相关阅读:
    vue 画/生成二维码
    2017年要学习的三个CSS新特性
    最好的Angular2表格控件
    最详细win7下手动搭建PHP环境:apache2.4.23+php7.0.11
    Javascript实现页面跳转的几种方式
    windows环境下sublime的nodejs插件详细安装图解
    CSS3 动画
    框架基础:ajax设计方案(一)---集成核心请求
    框架基础:ajax设计方案(二)---集成轮询技术
    框架基础:ajax设计方案(三)---集成ajax上传技术
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/14117304.html
Copyright © 2011-2022 走看看