来自Emgu CV的方法HoughCircles中的错误参数

时间:2013-12-27 15:54:22

标签: c# emgucv edge-detection

我正在尝试编写一个检测图像中硬币的应用程序。我发现了一段使用Emgu CV的HoughCircles的代码。但是,我无法设置参数,以便返回每个硬币(圆圈)。你对这个问题有经验吗?谢谢你的建议。

这是代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;

namespace INZO_Sem_Pr3_ST28605
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Bitmap bitmap = new Bitmap(pictureBox1.Image);

        //Load the image from file
        Image<Bgr, Byte> img = new Image<Bgr, byte>(bitmap);

        //Get and sharpen gray image (don't remember where I found this code; prob here on SO)
        Image<Gray, Byte> graySoft = img.Convert<Gray, Byte>().PyrDown().PyrUp();
        Image<Gray, Byte> gray = graySoft.SmoothGaussian(3);
        gray = gray.AddWeighted(graySoft, 1.5, -0.5, 0);

        Image<Gray, Byte> bin = gray.ThresholdBinary(new Gray(70), new Gray(255));

        Gray cannyThreshold = new Gray(200);
        Gray cannyThresholdLinking = new Gray(100);
        Gray circleAccumulatorThreshold = new Gray(1000);

        Image<Gray, Byte> cannyEdges = bin.Canny(cannyThreshold.Intensity, cannyThresholdLinking.Intensity);

        pictureBox1.Image = cannyEdges.ToBitmap();

        //Circles
        CircleF[] circles = cannyEdges.HoughCircles(
            cannyThreshold,
            circleAccumulatorThreshold,
            1.0, //Resolution of the accumulator used to detect centers of the circles
            cannyEdges.Height / 8, //min distance 
            0, //min radius
            2000 //max radius
            )[0]; //Get the circles from the first channel

        //draw circles (on original image)
        foreach (CircleF circle in circles)
            img.Draw(circle, new Bgr(Color.Brown), 2);
    }
}
}

我阅读了更多解释这些论点的含义,但我无法设定好的价值观。 这是使用边缘检测后的结果: enter image description here

1 个答案:

答案 0 :(得分:2)

让我们谈谈Hough变换。在其最简单的形式中,霍夫变换用于检测线条。这是通过获取图像中的每个“设置”像素并求解与该点相交的所有可能线来完成的。解决方案集本身就是一条线的等式。然后给出所有这些线方程,你解决它们之间的交叉点,最常见的交叉点的位置代表最“普遍”的线的解决方案。

实际上,这是通过将每个解决方案线的子集绘制到图像中来完成的,这样当您设置目标像素时,就会向其添加1。然后扫描图像并找到颜色最亮的像素,这是最流行的一行。 (实际上,你在极坐标中工作,但这是另一个故事)

对于圈子,它的工作方式类似,但在这里我们偷偷摸摸。我们确定了我们正在寻找的圆的半径以及图像中的每个“设置”像素,我们求解所有可以与该点相交的圆(它本身就是圆的方程)。然后找到这些圆的所有交点,最常见的交点是图像中固定半径最常见的圆。

实际上,这是通过以与线条示例完全相同的方式将每个解决方案圆绘制到图像上来完成的,并且图像中的“最亮”点是图像中最普遍的圆的中心。而在现实中,OpenCV使用梯度测试来减少计算。

现在,我对此的看法是,在documentation中,呼叫将首先运行Canny Edge检测。看起来您正在已经检测到边缘的图像上运行HoughCircles。不要那样做。

接下来,让我们看一下累加器阈值。这基本上就是说保持所有已经 n 或更多点击的圈子。通过将其设置为1000,您说每个圆圈必须至少有1000个解决方案集。太疯狂了。你应该使用你期望找到的最小半径圆周长的一定百分比。你越接近100%,圈子就越需要不间断。

dp参数用于确定解决方案空间应该有多大。 dp越接近0,则需要的内存越多)。随着dp的增长,结果越不准确。除非我的源图像是巨大,否则我不会使用超过2的任何内容。

min dist是允许圆圈重叠和多少。

最小和最大半径完全按照他们在盒子上的说法进行,但从0到1000是奇数。 0是“我不知道”的默认值,但我认为你最好用6或7这样的东西(12像素直径的圆圈大约可以渲染一个像样的圆圈)。那么最大值将是您认为对您的问题域合理的任何内容 - 例如100?

如果你想要更多细节,我前段时间写了a paper关于如何实现和更快地进行霍夫变换的方法。