【问题标题】:Detecting circles in binary image检测二值图像中的圆圈
【发布时间】:2014-09-28 16:28:40
【问题描述】:

您建议用什么算法来检测二值图像中的黑色圆圈?我正在使用的图像是白色的,还有一些其他对象以及我感兴趣的黑色圆圈。 我已经实现了用于圆检测的霍夫变换方法。问题是任何算法可以比霍夫变换快多少?

这些不是完美的圆,而且我只知道它们的半径的上下限:

【问题讨论】:

  • !perfect_circle == 椭圆
  • 是否有任何矩形总是水平/垂直的,或者它们可以任意旋转?
  • 矩形代表不同随机对象所在的区域。它们没有任何特定的形状。只是噪音、字母或任何东西。
  • 线条粗细、圆圈形状和大小是否与您的实际图像非常相似,或者只是粗略的近似?有噪音吗?最小半径值是多少? Hough 方法需要多长时间?如果 Hough 太慢,您需要在多长时间内完成?

标签: algorithm opencv image-processing


【解决方案1】:

您必须首先检测形状。这可以通过“连接组件分析”来完成。

要么你有这样一个现成的工具,要么你可以为你的目的制作一个简单的工具:实现flood filling algorithm,并按如下方式使用它:逐行扫描图像,直到遇到黑色像素.然后从这个像素填充填充,画成白色。这将使形状完全消失。继续扫描。最终图像将是全白的。

当然,如果您不跟踪发生的情况,这将完全没有用。在填充形状时,您将跟踪所访问像素的最小/最大横坐标和纵坐标。最后,您将知道形状的边界框。然后,您可以使用这个非常简单的标准来区分矩形和圆形:对于矩形,起始像素是边界框的左上角;不是为了一个圈子。 (其实,保持最小横坐标就够了)。

你明白了。如果您处于更复杂的情况(例如三角形),请遵循以下原则:执行斑点检测并测量斑点的一些几何特征;使用这些特征(它们称为“斑点特征”)来区分您的形状。

更新:

一个非常有判别力的测试可以如下:找到边界框并找到所有轮廓像素。然后对于每个轮廓像素检查(X-Xc)²/W²+(Y-Yc)²/H²=1/4,即它们位于以边界框为中心的椭圆上,轴为(W/2, H/2)。由于形状的数字特性,您需要添加 +/-1 像素容差。

【讨论】:

  • 实际上,除了圆圈之外,图像中还可以有字母,或者一些不相关的形状。我所知道的是圆圈与图像中的其他黑色像素分开。非常感谢您的想法。
【解决方案2】:

我有一个简单的代码,它利用了上一个答案中的一些提示,但使用了 OpenCV 函数:

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace std;
using namespace cv;

int main(int argc, char **argv){

    Mat img = imread("test.png", 0);

    Mat edge, out;

    Canny(img, edge, 1, 1);
    cvtColor(img, out, CV_GRAY2BGR);

    vector<vector<Point> > contours;
    vector<Vec4i> hierachy;

    findContours(edge, contours, hierachy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0));

    for(int i = 0; i < (int)contours.size(); i++){
        double p = (double)contours[i].size();
        double a = contourArea(contours[i]);

        if(fabs(1-pow(p,2)/(4*CV_PI*a)) < 0.2){
            drawContours(out, contours, i, Scalar(0,0,255), 2);
        }
    }

    imshow("out", out);
    waitKey(0);
    return 0;
}

基本思想很简单。您以像素方式检索边缘图像中的所有外部(最外层,因此为CV_RETR_EXTERNAL)轮廓(因此为CV_CHAIN_APPROX_NONE)。拥有它们后,您可以使用面积和周长来确定它们是否是圆。在此示例中,我使用了简单的测量值C=(P^2)/(4*PI*A),周长为P,面积为A。对于一个完美的圆,这将是 1,而偏离它的所有东西都不是一个圆。这当然只适用于不重叠的形状。

可能是简单的紧凑度测量不足以区分圆形与图像中可能存在的其他形状。但为此,我建议查看paper,它概述了一些循环性和紧凑性措施,或者查看一些image moments(例如偏心)和OpenCV 中的实现。也许您可以提出自己的标准。

这里是上面代码的output 给定您的测试图像。

【讨论】:

  • +1 不错的解决方案:我冒昧地为您粘贴了图片 - 希望没问题。
猜你喜欢
  • 2017-10-06
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 2023-01-01
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多