我正在尝试使用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 );
}
}
}
答案 0 :(得分:3)
根据新描述以及其他性能和准确度要求进行编辑。
这超出了“OpenCV示例项目”的范围,进入了实际应用程序开发的范围。性能和准确性都成为要求。
这需要结合技术。所以,不要只选择一种方法。您将不得不尝试所有方法组合,以及微调参数以找到可接受的组合。
使用缓慢但准确的方法获取初始检测结果。
一旦在一帧上发现正检测,下一帧应使用在最近帧上检测到的位置切换到快速本地搜索算法。
提醒一下,不要忘记更新下一帧使用的“最近位置”。
继续使用您当前的方法,并纳入建议。
您仍然可以微调速度和精度之间的平衡,因为当使用本地搜索方法处理下一帧时,将更新和改进正确但不精确的结果(减去数十个像素)。 / p>
dp
参数的建议。 <子>
较大的dp
值会降低执行Hough Gradient变换的分辨率。这会降低中心坐标的精度,但会提高检测凹陷圆的几率,因为当以较低分辨率执行变换时凹痕将变得不那么重要。
子>
<子> 另一个好处是降低分辨率应该更快。 子>
<子> 由于搜索空间和所需数据量有限,因此可以使本地搜索既快速又精确。 子>
为了通过视频帧跟踪虹膜边界的移动,我建议使用一系列称为 Snakes模型的算法。
重点是跟踪通过轮廓的边缘移动。有许多算法可以实现Snakes模型。不幸的是,大多数实现都是针对非常复杂的形状识别而定制的,这对于您的项目来说太过分了,而且速度太慢。
基本思路:(假设前一个结果是曲线)
您可以在互联网上找到很多种类,不同级别的实施方案。不幸的是,据报道the one packaged with OpenCV might not work very well.您可能必须尝试不同的开源实现,最终您可能必须实现一个简单但适合您项目需求的方法。
在每次调用OpenCV函数时添加一些计时和日志代码,以打印出每个步骤所花费的时间。 你会感到惊讶。原因是一些OpenCV函数比其他函数更加矢量化和并行化,可能是因为爱的劳动。
不幸的是,对于最慢的步骤 - 初始对象获取,没有太多可以并行化(通过多线程)。
这可能已经很明显了,因为你没有将#pragma omp for
放在第一个代码块周围。 (无论如何,这都无济于事。)
子>
<子>
我的猜测是cvtColor
,GaussianBlur
,threshold
,dilate
,erode
可以被矢量化,但其他可能不是。
子>
答案 1 :(得分:0)
在下面试试,
在源中查找轮廓。
找出轮廓的最小封闭圆圈。
现在使用CV_FILLED将轮廓绘制到新Mat。
同样使用填充选项将封闭圆绘制到新Mat。
在上述两者之间执行x或操作并计算非零。
通过将轮廓和包围圆之间的非零像素与阈值进行比较,可以确定轮廓是否接近圆。您可以通过计算圆圈的面积并将其取百分比来确定阈值。
这个想法很简单,轮廓与其圆圈之间的区域随着轮廓接近圆而减小