检测类似于圆的对象 [英] Detect objects similar to circles

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

问题描述

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

有人知道检测类似于此类圆圈的物体的任何其他方法吗?

更新

更新

Hello Folks我正在添加检测方法结果的gif图像.

使用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 );
                }   
            }
        }

解决方案

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


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

这需要多种技术的结合.因此,不要只选择一种方法.您将必须尝试所有方法的组合,并微调参数以找到可接受的组合.


#1.连续视频帧识别任务的总体方法

  • 使用一种缓慢但准确的方法来获取初始检测结果.

  • 一旦在一帧上检测到阳性,则下一帧应使用在最近一帧上检测到的位置切换到快速的局部搜索算法.

    li>

提醒一下,不要忘记更新最新位置"以供下一帧使用.


#2.初始物体获取的建议.

  • 继续使用当前的方法,并结合建议.

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

    • 尝试我提出的增加dp参数的建议.

较大的dp值会降低执行霍夫梯度变换的分辨率.这会降低中心坐标的精度,但会提高检测到凹陷圆的机会,因为当以较低的分辨率执行变换时,凹痕的重要性将降低.

另一个好处是降低的分辨率应该运行得更快.


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

由于搜索空间和所需数据量有限,因此可以快速而精确地进行本地搜索.

要跟踪虹膜边界在视频帧中的运动,我建议使用称为 Snakes模型的一系列算法.

重点是通过轮廓跟踪边缘的运动.有许多算法可以实现Snakes模型.不幸的是,大多数实现都是针对非常复杂的形状识别而量身定制的,这对于您的项目来说是一个过大的选择,并且太慢了.

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

  1. 在曲线上选择一些采样点.
  2. 使用旧框架的位置在新框架上的每个采样点扫描边缘轮廓(垂直于曲线).寻找最大的变化.
  3. 记住该采样点的新边缘位置.
  4. 所有采样点均已更新后,通过将所有更新的采样点位置连接起来来创建一条新曲线.

您可以在Internet上找到各种各样的实现,以及不同级别的实现.不幸的是,据报道,与OpenCV打包的软件包可能不起作用很好.您可能必须尝试不同的开源实现,最终您可能必须实现一种简单但可以根据项目需求进行适当调整的实现.


#4.寻求有关速度优化尝试的建议.

  • 使用软件性能分析器.

  • 在每次调用OpenCV函数的周围添加一些计时和日志记录代码,以打印出每个步骤所花费的时间. 您会感到惊讶.原因是某些OpenCV函数的向量化和并行化程度比其他函数高,这可能是由于爱的努力.

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

这对您来说可能已经很明显了,因为您没有将#pragma omp for放在第一段代码中. (无论如何也无济于事.)

    矢量化(SIMD)仅有益于像素级处理.如果OpenCV实现了,那就太好了;如果没有,您将无能为力.

我的猜测是cvtColorGaussianBlurthresholddilateerode本来可以被矢量化的,但其他的可能不是.


I'm trying to detect objects that are similar to circles using OpenCV's HoughCircles. The problem is: HoughCircles fails to detect such objects in some cases.

Does anyone know any alternative way to detect objects similar to circles like these ones?

Update

Update

Hello Folks I'm adding a gif of the result of my detection method.

It's easier use a gif to explain the problem. The undesired effect that I want to remove is the circle size variation. Even for a static shape like the one on the right, the result on the left is imprecise. Does anyone know a solution for that?

Update All that I need from this object is its diameter. I've done it using findContours. Now I can't use findContours once it is too slow when using openCV and OpenMP. Does anyone know a fast alternatives to findContours?

Update

The code that I'm using to detect these shapes.

     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 );
                }   
            }
        }

解决方案

Edited based on new description and additional performance and accuracy requirements.


This is getting beyond the scope of an "OpenCV sample project", and getting into the realm of actual application development. Both performance and accuracy become requirements.

This requires a combination of techniques. So, don't just pick one approach. You will have to try all combinations of approaches, as well as fine-tune the parameters to find an acceptable combination.


#1. overall approach for continuous video frame recognition tasks

  • Use a slow but accurate method to acquire an initial detection result.

  • Once a positive detection is found on one frame, the next frame should switch to a fast local search algorithm using the position detected on the most recent frame.

As a reminder, don't forget to update the "most recent position" for use by the next frame.


#2. suggestion for initial object acquisition.

  • Stay with your current approach, and incorporate the suggestions.

  • You can still fine-tune the balance between speed and precision, because a correct but imprecise result (off by tens of pixels) will be updated and refined when the next frame is processed with the local search approach.

    • Try my suggestion of increasing the dp parameter.

A large value of dp reduces the resolution at which Hough Gradient Transform is performed. This reduces the precision of the center coordinates, but will improve the chance of detecting a dented circle because the dent will become less significant when the transform is performed at a lower resolution.

An added benefit is that reduced resolution should run faster.


#3. suggestion for fast local search around a previously detected position

Because of the limited search space and amount of data needed, it is possible to make local search both fast and precise.

For tracking the movement of the boundary of iris through video frames, I suggest using a family of algorithms called the Snakes model.

The focus is on tracking the movement of edges through profiles. There are many algorithms that can implement the Snakes model. Unfortunately, most implementations are tailored to very complex shape recognition, which would be an overkill and too slow for your project.

Basic idea: (assuming that the previous result is a curve)

  1. Choose some sampling points on the curve.
  2. Scan the edge profile (perpendicular to the curve) at each the sampling point, on the new frame, using the position of the old frame. Look for the sharpest change.
  3. Remember the new edge position for this sampling point.
  4. After all of the sampling points have been updated, create a new curve by joining all of the updated sampling point positions.

There are many varieties, and different levels of sophistication of implementations which you can find on the Internet. Unfortunately, it was reported that the one packaged with OpenCV might not work very well. You may have to try different open-source implementation, and ultimately you may have to implement one that is simple but well-tuned to your project's needs.


#4. Seek advice for your speed optimization attempts.

  • Use a software performance profiler.

  • Add some timing and logging code around each call to OpenCV function to print out the time spent on each step. You will be surprised. The reason is that some OpenCV functions are more heavily vectorized and parallelized than others, perhaps as a result of the labor of love.

  • Unfortunately, for the slowest step - initial object acquisition, there is not much you can parallelize (by multithread).

This is perhaps already obvious to you since you did not put #pragma omp for around the first block of code. (It would not help anyway.)

  • Vectorization (SIMD) would only benefit pixel-level processing. If OpenCV implements it, great; if not, there is not much you can do.

My guess is that cvtColor, GaussianBlur, threshold, dilate, erode could have been vectorized, but the others might not be.


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

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