直接在圖片上使用houghCircle
,不要先提取邊緣。 然後測試每個檢測到的圓,多百分比如何在圖像中確實存在:
int main()
{
cv::Mat color = cv::imread("../houghCircles.png");
cv::namedWindow("input"); cv::imshow("input", color);
cv::Mat canny;
cv::Mat gray;
/// Convert it to gray
cv::cvtColor(color, gray, CV_BGR2GRAY);
// compute canny (don't blur with that image quality!!)
cv::Canny(gray, canny, 200,20);
cv::namedWindow("canny2"); cv::imshow("canny2", canny>0);
std::vector<cv::Vec3f> circles;
/// Apply the Hough Transform to find the circles
cv::HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 1, 60, 200, 20, 0, 0);
/// Draw the circles detected
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]);
cv::circle(color, center, 3, Scalar(0,255,255), -1);
cv::circle(color, center, radius, Scalar(0,0,255), 1);
}
//compute distance transform:
cv::Mat dt;
cv::distanceTransform(255-(canny>0), dt, CV_DIST_L2 ,3);
cv::namedWindow("distance transform"); cv::imshow("distance transform", dt/255.0f);
// test for semi-circles:
float minInlierDist = 2.0f;
for(size_t i = 0; i < circles.size(); i++)
{
// test inlier percentage:
// sample the circle and check for distance to the next edge
unsigned int counter = 0;
unsigned int inlier = 0;
cv::Point2f center((circles[i][0]), (circles[i][1]));
float radius = (circles[i][2]);
// maximal distance of inlier might depend on the size of the circle
float maxInlierDist = radius/25.0f;
if(maxInlierDist<minInlierDist) maxInlierDist = minInlierDist;
//TODO: maybe paramter incrementation might depend on circle size!
for(float t =0; t<2*3.14159265359f; t+= 0.1f)
{
counter++;
float cX = radius*cos(t) + circles[i][0];
float cY = radius*sin(t) + circles[i][1];
if(dt.at<float>(cY,cX) < maxInlierDist)
{
inlier++;
cv::circle(color, cv::Point2i(cX,cY),3, cv::Scalar(0,255,0));
}
else
cv::circle(color, cv::Point2i(cX,cY),3, cv::Scalar(255,0,0));
}
std::cout << 100.0f*(float)inlier/(float)counter << " % of a circle with radius " << radius << " detected" << std::endl;
}
cv::namedWindow("output"); cv::imshow("output", color);
cv::imwrite("houghLinesComputed.png", color);
cv::waitKey(-1);
return 0;
}
對於此輸入:
它給出了這樣的輸出:
紅圈是霍夫結果。
圓圈上的綠色採樣點是正常值。
藍點是異常值。
控制檯輸出:
100 % of a circle with radius 27.5045 detected
100 % of a circle with radius 25.3476 detected
58.7302 % of a circle with radius 194.639 detected
50.7937 % of a circle with radius 23.1625 detected
79.3651 % of a circle with radius 7.64853 detected
如果你想測試RANSAC而不是霍夫,看看this。
是它的權利,你可以邊哪個/檢測(後精明和Hough)圖像中屬於圈半圈?而你的問題是,霍夫結果的圈子位置不夠好? 如何用所有圓邊(或至少3個正確的圓邊像素)擬合參數化圓? (三點定義一個圓圈!)...爲了使它更健壯,你可以使用RANSAC算法(inlier/outlier counting =>巨大的缺失部分=半圓)。 沒有嘗試過,但可能有效?!? – Micka
謝謝米卡!你所說的參數化圓是霍夫變換算法本身,不是嗎?如果你看到霍夫的結果,在檢測到的圓上有3個以上的位置!我對RANSAC毫無頭緒,我會檢查出來 – harsh
在計算/繪製圓圈之前,您能否提供邊緣圖像? 您是否嘗試用較少的線條厚度繪製輪廓? – Micka