gpt4 book ai didi

c++ - RobuSTLy 找到 N 个直径相同的圆 : alternative to bruteforcing Hough transform threshold

转载 作者:IT老高 更新时间:2023-10-28 22:20:28 24 4
gpt4 key购买 nike

我正在开发应用程序来跟踪培养皿(或其他圆形容器)中的小动物。在进行任何跟踪之前,前几帧用于定义区域。每道菜都会匹配一个圆形独立静态区域(即在跟踪期间不会更新)。用户可以请求程序尝试从原始图像中查找菜肴并将其用作区域。

以下是示例: enter image description here enter image description here

为了执行这个任务,我使用 霍夫圆变换。但实际上,不同的用户会有非常不同的设置和图像,我不想让用户手动定义参数。我也不能只猜测所有参数。

但是,我还有一些我想使用的其他信息:

我知道要检测的圆圈的确切数量。

  • 所有圆圈的尺寸几乎相同。
  • 圆圈不能重叠。
  • 我对圆圈的最小和最大尺寸有一个粗略的了解。
  • 圆圈必须完全在图片中。

因此,我可以将要定义的参数数量缩小到一个:阈值。使用这些信息并考虑到我有 N 个圈子要找到,我目前的解决方案是测试多个阈值并保留标准差最小的圆圈(因为所有圆圈都应该具有相似的大小):

//at this point, minRad and maxRad were calculated from the size of the image and the number of circles to find.
//assuming circles should altogether fill more than 1/3 of the images but cannot be altogether larger than the image.
//N is the integer number of circles to find.
//img is the picture of the scene (filtered).

//the vectors containing the detected circles and the --so far-- best circles found.
std::vector<cv::Vec3f> circles, bestCircles;

//the score of the --so far-- best set of circles
double bestSsem = 0;

for(int t=5; t<400 ; t=t+2){
//Apply Hough Circles with the threshold t
cv::HoughCircles(img, circles, CV_HOUGH_GRADIENT, 3, minRad*2, t,3, minRad, maxRad );

if(circles.size() >= N){
//call a routine to give a score to this set of circles according to the similarity of their radii
double ssem = scoreSetOfCircles(circles,N);
//if no circles are recorded yet, or if the score of this set of circles is higher than the former best
if( bestCircles.size() < N || ssem > bestSsem){
//this set become the temporary best set of circles
bestCircles=circles;
bestSsem=ssem;
}
}
}

与:

 //the methods to assess how good is a set of circle (the more similar the circles are, the higher is ssem)
double scoreSetOfCircles(std::vector<cv::Vec3f> circles, int N){
double ssem=0, sum = 0;
double mean;
for(unsigned int j=0;j<N;j++){
sum = sum + circles[j][2];
}
mean = sum/N;
for(unsigned int j=0;j<N;j++){
double em = mean - circles[j][2];
ssem = 1/(ssem + em*em);
}
return ssem;

}

通过执行第二遍,我已经达到了更高的准确度,其中我重复了这个算法,使用第一遍的结果缩小了 [minRad:maxRad] 区间。

例如 minRad2 = 0.95 * 最佳圆的平均半径和 maxRad2 = 1.05 * 最佳圆的平均半径。

到目前为止,我使用这种方法取得了相当好的结果。但是,它很慢而且很脏。我的问题是:

  • 你能想到任何替代算法以更清洁/更快的方式解决这个问题吗?
  • 或者你有什么建议来改进这个算法?
  • 你认为我应该研究广义霍夫变换吗?

感谢您的回答和建议。

最佳答案

以下方法应该非常适合您的情况:

  1. 对图像进行二值化(您可能需要在多个阈值级别上执行此操作,以使算法独立于光照条件)
  2. 寻找轮廓
  3. 为每个轮廓计算矩
  4. 按区域过滤它们以去除太小的轮廓
  5. 按圆度过滤轮廓:

    double area = moms.m00;
    double perimeter = arcLength(Mat(contours[contourIdx]), true);
    double ratio = 4 * CV_PI * area / (perimeter * perimeter);

    ratio 接近 1 会给你圈子。

  6. 计算每个圆的半径和圆心

    center = Point2d(moms.m10 / moms.m00, moms.m01 / moms.m00);

您可以添加更多过滤器来提高鲁棒性。

实际上,您可以在 OpenCV 中找到整个过程的实现。看看 SimpleBlobDetector 类和 findCirclesGrid 函数是如何实现的。

关于c++ - RobuSTLy 找到 N 个直径相同的圆 : alternative to bruteforcing Hough transform threshold,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10873710/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com