检测类似于圆圈的对象

时间:2014-03-08 20:52:48

标签: opencv

我正在尝试使用OpenCV的HoughCircles检测与圆圈类似的对象。问题是:HoughCircles在某些情况下无法检测到此类对象。

有没有人知道检测类似于这些圆圈的对象的替代方法?

更新 enter image description here

更新

Hello Folks我正在添加一个检测方法结果的gif。

enter image description here

使用gif更容易解释问题。我想要删除的不良效果是圆圈大小变化。即使对于像右边那样的静态形状,左边的结果也是不精确的。有谁知道解决方案吗?

更新 我需要的就是它的直径。我是用findContours完成的。现在,一旦使用openCV和OpenMP太慢,我就无法使用findContours。有没有人知道findContours的快速替代品?

更新

我用来检测这些形状的代码。

     for (int j=0; j<=NUM_THREADS-1;j++)
        {
            capture >> frame[j];
        }


        #pragma omp parallel shared(frame,processOutput,circles,diameterArray,diameter) 
        {  

            int n=omp_get_thread_num();
            cvtColor( frame[n], processOutput[n], CV_BGR2GRAY);

            GaussianBlur(processOutput[n],  processOutput[n],  Size(9, 9), 2, 2);
            threshold(processOutput[n],  processOutput[n], 21, 250, CV_THRESH_BINARY);

            dilate(processOutput[n],  processOutput[n], Mat(), Point(-1, -1), 2, 1, 1);
            erode(processOutput[n],  processOutput[n], Mat(), Point(-1, -1), 2, 1, 1);

            Canny(processOutput[n],  processOutput[n], 20, 20*2, 3 );

            HoughCircles( processOutput[n],circles[n], CV_HOUGH_GRADIENT, 1, frame[n].rows/8, 100,21, 50, 100);

        }

        #pragma omp parallel private(m, n) shared(circles)
        {
            #pragma omp for
            for (n=0; n<=NUM_THREADS-1;n++)
            {
                for( m = 0; m < circles[n].size(); m++ ) 
                {
                    Point center(cvRound(circles[n][m][0]), cvRound(circles[n][m][2]));
                    int radius = cvRound(circles[n][m][3]);
                    diameter = 2*radius;
                    diameterArray[n] = diameter;
                    circle( frame[0], center, 3, Scalar(0,255,0), -1, 8, 0 );
                    circle( frame[0], center, radius, Scalar(0,0,255), 3, 8, 0 );
                }   
            }
        }

2 个答案:

答案 0 :(得分:3)

根据新描述以及其他性能和准确度要求进行编辑。


这超出了“OpenCV示例项目”的范围,进入了实际应用程序开发的范围。性能和准确性都成为要求。

这需要结合技术。所以,不要只选择一种方法。您将不得不尝试所有方法组合,以及微调参数以找到可接受的组合。


#1。连续视频帧识别任务的整体方法

  • 使用缓慢但准确的方法获取初始检测结果。

  • 一旦在一帧上发现正检测,下一帧应使用在最近帧上检测到的位置切换到快速本地搜索算法。

提醒一下,不要忘记更新下一帧使用的“最近位置”。


#2。建议初始对象获取。

  • 继续使用您当前的方法,并纳入建议。

  • 您仍然可以微调速度和精度之间的平衡,因为当使用本地搜索方法处理下一帧时,将更新和改进正确但不精确的结果(减去数十个像素)。 / p>

    • 尝试增加dp参数的建议。

<子> 较大的dp值会降低执行Hough Gradient变换的分辨率。这会降低中心坐标的精度,但会提高检测凹陷圆的几率,因为当以较低分辨率执行变换时凹痕将变得不那么重要。

<子> 另一个好处是降低分辨率应该更快。


#3。建议在先前检测到的位置周围进行快速本地搜索

<子> 由于搜索空间和所需数据量有限,因此可以使本地搜索既快速又精确

为了通过视频帧跟踪虹膜边界的移动,我建议使用一系列称为 Snakes模型的算法。

重点是跟踪通过轮廓的边缘移动。有许多算法可以实现Snakes模型。不幸的是,大多数实现都是针对非常复杂的形状识别而定制的,这对于您的项目来说太过分了,而且速度太慢。

基本思路:(假设前一个结果是曲线)

  1. 在曲线上选择一些采样点。
  2. 使用旧框架的位置扫描新框架上每个采样点的边缘轮廓(垂直于曲线)。寻找最明显的变化。
  3. 记住此采样点的新边缘位置。
  4. 在更新所有采样点后,通过连接所有更新的采样点位置来创建新曲线。
  5. 您可以在互联网上找到很多种类,不同级别的实施方案。不幸的是,据报道the one packaged with OpenCV might not work very well.您可能必须尝试不同的开源实现,最终您可能必须实现一个简单但适合您项目需求的方法。


    #4。寻求速度优化尝试的建议。

    • 使用software performance profiler

    • 在每次调用OpenCV函数时添加一些计时和日志代码,以打印出每个步骤所花费的时间。 你会感到惊讶。原因是一些OpenCV函数比其他函数更加矢量化和并行化,可能是因为爱的劳动。

    • 不幸的是,对于最慢的步骤 - 初始对象获取,没有太多可以并行化(通过多线程)。

    这可能已经很明显了,因为你没有将#pragma omp for放在第一个代码块周围。 (无论如何,这都无济于事。)

    • 矢量化(SIMD)只会使像素级处理受益。如果OpenCV实现它,那很好;如果没有,你可以做的并不多。

    <子> 我的猜测是cvtColorGaussianBlurthresholddilateerode可以被矢量化,但其他可能不是。


答案 1 :(得分:0)

在下面试试,

  1. 在源中查找轮廓。

  2. 找出轮廓的最小封闭圆圈。

  3. 现在使用CV_FILLED将轮廓绘制到新Mat。

  4. 同样使用填充选项将封闭圆绘制到新Mat。

  5. 在上述两者之间执行x或操作并计算非零。

  6. 通过将轮廓和包围圆之间的非零像素与阈值进行比较,可以确定轮廓是否接近圆。您可以通过计算圆圈的面积并将其取百分比来确定阈值。

  7. 这个想法很简单,轮廓与其圆圈之间的区域随着轮廓接近圆而减小