在OpenCV中检测半圆 [英] Detect semicircle in OpenCV

查看:833
本文介绍了在OpenCV中检测半圆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测图像中的完整圆形和半圆形.

I am trying to detect full circles and semicircles in an image.

我正在执行以下提到的过程: 过程映像(包括Canny边缘检测). 查找轮廓并将其绘制在空白图像上,以便消除不必要的成分 (处理后的图像正是我想要的). 使用HoughCircles检测圆.而且,这就是我得到的:

I am following the below mentioned procedure: Process image (including Canny edge detection). Find contours and draw them on an empty image, so that I can eliminate unwanted components (The processed image is exactly what I want). Detect circles using HoughCircles. And, this is what I get:

我尝试更改HoughCircles中的参数,但结果不一致,因为它根据光照和图像中圆圈的位置而变化. 我根据圆形的大小接受或拒绝圆形.因此,结果是不可接受的.另外,我有一长串可接受的"圈子.因此,我在HoughCircle参数中需要一些津贴. 至于完整的圆,这很容易-我可以简单地找到轮廓的圆度".问题是半圆!

I tried varying the parameters in HoughCircles but the results are not consistent as it varies based on lighting and the position of circles in the image. I accept or reject a circle based on its size. So, the result is not acceptable. Also, I have a long list of "acceptable" circles. So, I need some allowance in the HoughCircle params. As for the full circles, it's easy - I can simply find the "roundness" of the contour. The problem is semicircles!

请在霍夫变换之前找到编辑后的图像

Please find the edited image before Hough transform

推荐答案

直接在图像上使用houghCircle,不要先提取边缘. 然后针对每个检测到的圆测试图像中实际存在的百分比:

Use houghCircle directly on your image, don't extract edges first. Then test for each detected circle, how much percentage is really present in the image:

int main()
{
    cv::Mat color = cv::imread("../houghCircles.png");
    cv::namedWindow("input"); cv::imshow("input", color);

    cv::Mat canny;

    cv::Mat gray;
    /// Convert it to gray
    cv::cvtColor( color, gray, CV_BGR2GRAY );

    // compute canny (don't blur with that image quality!!)
    cv::Canny(gray, canny, 200,20);
    cv::namedWindow("canny2"); cv::imshow("canny2", canny>0);

    std::vector<cv::Vec3f> circles;

    /// Apply the Hough Transform to find the circles
    cv::HoughCircles( gray, circles, CV_HOUGH_GRADIENT, 1, 60, 200, 20, 0, 0 );

    /// Draw the circles detected
    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]);
        cv::circle( color, center, 3, Scalar(0,255,255), -1);
        cv::circle( color, center, radius, Scalar(0,0,255), 1 );
    }

    //compute distance transform:
    cv::Mat dt;
    cv::distanceTransform(255-(canny>0), dt, CV_DIST_L2 ,3);
    cv::namedWindow("distance transform"); cv::imshow("distance transform", dt/255.0f);

    // test for semi-circles:
    float minInlierDist = 2.0f;
    for( size_t i = 0; i < circles.size(); i++ ) 
    {
        // test inlier percentage:
        // sample the circle and check for distance to the next edge
        unsigned int counter = 0;
        unsigned int inlier = 0;

        cv::Point2f center((circles[i][0]), (circles[i][1]));
        float radius = (circles[i][2]);

        // maximal distance of inlier might depend on the size of the circle
        float maxInlierDist = radius/25.0f;
        if(maxInlierDist<minInlierDist) maxInlierDist = minInlierDist;

        //TODO: maybe paramter incrementation might depend on circle size!
        for(float t =0; t<2*3.14159265359f; t+= 0.1f) 
        {
            counter++;
            float cX = radius*cos(t) + circles[i][0];
            float cY = radius*sin(t) + circles[i][1];

            if(dt.at<float>(cY,cX) < maxInlierDist) 
            {
                inlier++;
                cv::circle(color, cv::Point2i(cX,cY),3, cv::Scalar(0,255,0));
            } 
           else
                cv::circle(color, cv::Point2i(cX,cY),3, cv::Scalar(255,0,0));
        }
        std::cout << 100.0f*(float)inlier/(float)counter << " % of a circle with radius " << radius << " detected" << std::endl;
    }

    cv::namedWindow("output"); cv::imshow("output", color);
    cv::imwrite("houghLinesComputed.png", color);

    cv::waitKey(-1);
    return 0;
}

对于此输入:

它给出以下输出:

红色圆圈是霍夫的结果.

The red circles are Hough results.

圆上的绿色采样点是内点.

The green sampled dots on the circle are inliers.

蓝点是异常值.

控制台输出:

100 % of a circle with radius 27.5045 detected
100 % of a circle with radius 25.3476 detected
58.7302 % of a circle with radius 194.639 detected
50.7937 % of a circle with radius 23.1625 detected
79.3651 % of a circle with radius 7.64853 detected

如果要测试RANSAC而不是Hough,请查看

If you want to test RANSAC instead of Hough, have a look at this.

这篇关于在OpenCV中检测半圆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆