你已经知道图像中的小圆圈(你用黑色绘制)。
- 使用这些圆来准备掩模图像,使具有较小圆的区域将具有非零像素。我们叫它掩盖:
- 在原始图像中,深色填补这些领域圈(说黑)。这将导致像你的图2的图像。我们将其称为填充
- 阈值的填充图像以获得黑暗的地区。我们将其称为二进制。你可以使用Otsu为此设定阈值。结果会是这个样子:
- 乘坐距离变换这二进制形象。为此使用精确的距离估计方法。我们将这个称为dist。它看起来像这样。彩色一个仅仅是为了更清楚的热图:
- 使用面具从DIST获得峰值区域。每个这样的区域的最大值应该给你更大的圆的半径。您也可以对这些区域进行一些处理,以获得更为合理的半径值,而不仅仅是拾取最大值。
- 对于选择区域,您可以找到面具的轮廓,然后从DIST图像提取区域,或者,因为你已经知道,从应用霍夫圆变换的小圆圈,准备从面具每个圈子从dist图像中提取该区域。我不确定你是否可以通过掩码来计算最大或其他属性。 Max肯定会工作,因为其余像素都是0.如果将这些像素提取到另一个阵列,则可能可以计算该区域的统计信息。
下图显示了这样的面罩和从dist提取的区域。为此,我得到最大值约为29,与该圆的半径一致。请注意,图像不是按比例绘制的。
掩模圆形,提取出的区域从DIST
下面的代码(我不使用霍夫圆变换):
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();
结果(换算):
希望这会有所帮助。
你能显示你的HoughCircles代码吗?重叠/半圈等通常不是HoughCircles afaik的问题。 – Micka 2014-09-04 13:44:08
谢谢Micka我只是加了一些代码 – coincoin 2014-09-04 13:56:49
你可以把maskedImage保存到一个文件('imwrite(“maskedImage.jpg”,maskedImage)')并发布一个链接吗? – 2014-09-04 14:01:21