gpt4 book ai didi

opencv - 使用 OpenCV 查找重叠/复杂的圆

转载 作者:太空宇宙 更新时间:2023-11-03 20:52:37 25 4
gpt4 key购买 nike

我想计算红色圆圈的半径(图 2)。我无法使用 OpenCV 中的 HoughCircles 找到这些圈子。如图所示。 2 我只能使用 HoughCircles 找到中心显示为黑色的小圆圈。

原创pic1图 2。red

因为我知道红色圆圈的中心(与红色圆圈相同),有没有办法简单地计算红色圆圈的半径?

是否也可以有一种通用的方法来计算更复杂的图像(例如这幅图像)上的圆半径:

example 2

编辑:这里是获得图 2 后我的代码中有趣的部分:

threshold(maskedImage, maskedImage, thresh, 255, THRESH_BINARY_INV | THRESH_OTSU);
std::vector<Vec3f> circles;
// Canny(maskedImage, maskedImage, thresh, thresh * 2, 3);

HoughCircles(maskedImage, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 4, cannyThreshold, accumulatorThreshold, 0, 0);

Mat display = src_display.clone();
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
// circle center
circle(display, center, 3, Scalar(0, 255, 0), -1, 8, 0);
// circle outline
circle(display, center, radius, Scalar(0, 0, 255), 3, 8, 0);
}

我尝试使用 cannyThreshold 和 accumulator 玩游戏,但没有结果。真实图像大 5 倍。这里a link例如阈值后的 1。

谢谢

最佳答案

你已经知道图像中的小圆圈(你用黑色画的)。

  • 使用这些圆圈准备蒙版图像,这样圆圈较小的区域将具有非零像素。我们称之为面具:

enter image description here

  • 在原始图像中,用深色(比如黑色)填充这些圆圈区域。这将生成类似于图 2 的图像。我们将其称为填充
  • 填充图像进行阈值处理以获得暗区。我们称之为二进制。您可以为此使用 Otsu 阈值。结果将如下所示:

enter image description here

  • 对这张二进制 图像进行距离变换。为此使用准确的距离估计方法。我们称之为 dist。它看起来像这样。为了更清楚起见,彩色的只是一张热图:

enter image description here enter image description here

  • 使用ma​​skdist 获取峰区域。每个这样的区域的最大值应该给你更大的圆的半径。您还可以对这些区域进行一些处理,以获得更合理的半径值,而不仅仅是选择最大值。
  • 要选择区域,您可以找到ma​​sk 的轮廓,然后从dist 图像中提取该区域,或者,因为您已经知道来自应用 hough-circle 变换,从每个圆圈中准备一个蒙版,并从 dist 图像中提取该区域。我不确定你是否可以通过给面具来计算最大值或其他统计数据。 Max 肯定会起作用,因为其余像素为 0。如果将这些像素提取到另一个数组,您可能能够计算该区域的统计数据。

下图显示了这样的蒙版和从 dist 中提取的区域。为此,我得到的最大值约为 29,这与该圆的半径一致。请注意,图片未按比例缩放。

圆圈的 mask ,从 dist 中提取的区域

enter image description here enter image description here

这是代码(我没有使用霍夫圆变换):

    Mat im = imread(INPUT_FOLDER_PATH + string("ex1.jpg"));

Mat gray;
cvtColor(im, gray, CV_BGR2GRAY);

Mat bw;
threshold(gray, bw, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU);
// filtering smaller circles: not using hough-circles transform here.
// you can replace this part with you hough-circles code.
vector<int> circles;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
{
Rect rect = boundingRect(contours[idx]);
if (abs(1.0 - ((double)rect.width/rect.height) < .1))
{
Mat mask = Mat::zeros(im.rows, im.cols, CV_8U);
drawContours(mask, contours, idx, Scalar(255, 255, 255), -1);
double area = sum(mask).val[0]/255;
double rad = (rect.width + rect.height)/4.0;
double circArea = CV_PI*rad*rad;
double dif = abs(1.0 - area/circArea);
if (dif < .5 && rad < 50 && rad > 30) // restrict the radius
{
circles.push_back(idx); // store smaller circle contours
drawContours(gray, contours, idx, Scalar(0, 0, 0), -1); // fill circles
}
}
}

threshold(gray, bw, 0, 255, CV_THRESH_BINARY_INV|CV_THRESH_OTSU);

Mat dist, distColor, color;
distanceTransform(bw, dist, CV_DIST_L2, 5);
double max;
Point maxLoc;
minMaxLoc(dist, NULL, &max);
dist.convertTo(distColor, CV_8U, 255.0/max);
applyColorMap(distColor, color, COLORMAP_JET);
imshow("", color);
waitKey();

// extract dist region corresponding to each smaller circle and find max
for(int idx = 0; idx < (int)circles.size(); idx++)
{
Mat masked;
Mat mask = Mat::zeros(im.rows, im.cols, CV_8U);
drawContours(mask, contours, circles[idx], Scalar(255, 255, 255), -1);
dist.copyTo(masked, mask);
minMaxLoc(masked, NULL, &max, NULL, &maxLoc);
circle(im, maxLoc, 4, Scalar(0, 255, 0), -1);
circle(im, maxLoc, (int)max, Scalar(0, 0, 255), 2);
cout << "rad: " << max << endl;
}
imshow("", im);
waitKey();

结果(缩放):

enter image description here enter image description here

希望这对您有所帮助。

关于opencv - 使用 OpenCV 查找重叠/复杂的圆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25667053/

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