我正在寻找激光光斑的中心和半径,我计划通过在 Visual C++ 的 opencv 3.2 中使用 HoughCircle 算法来完成。
我的一个示例图像是一个定义非常明确的点,但返回的霍夫圆与我的预期大不相同。下面是原始图像和处理后的图像的截图,紫色圆圈是我的期望值,红色圆圈是计算出的霍夫。我有控制 Hough 调用的 dp、param1 和 param2 的轨迹栏。在第一对图像中,我只对处理后的图像进行了模糊和阈值处理,在第二对图像中,我使用 5x5 椭圆蒙版膨胀了一次。
我已经移动了霍夫参数的滑块,但这两个圆圈是我得到的最佳近似值,而且都不正确。使用的参数是:Hough1 = 100, Hough2= 21, dp= 1。我认为我不需要调整模糊、阈值或膨胀参数,因为我认为当前的圆应该足够好,可以更好地估计. 下面是没有膨胀的点的 Canny 视图:
当我将膨胀迭代增加到 7 并调整我的霍夫参数时,我得到了许多看起来不准确的圆圈。当我减小霍夫参数 2 时,最终会出现一些看起来最合适的圆圈,但可能是第 10 个出现的圆圈。下面是一张带有额外膨胀和较低 dp/param2 值的图像,绿色圆圈代表一个 Hough 圆圈,它与我手动估计的紫色圆圈相当接近。
我可以采取哪些步骤来自动抓取和隔离人类用户会接受为合理的最佳拟合的圆圈?
代码:
int houghParam1 = 100;
int houghParam2 = 100;
int dp = 10; //divided by 10 later
int x=616;
int y=444;
int radius = 398;
int iterations = 0;
int main()
{
namedWindow("Circled Orig");
namedWindow("Processed", 1);
namedWindow("Circles");
namedWindow("Parameters");
namedWindow("Canny");
createTrackbar("Param1", "Parameters", &houghParam1, 200);
createTrackbar("Param2", "Parameters", &houghParam2, 200);
createTrackbar("dp", "Parameters", &dp, 20);
createTrackbar("x", "Parameters", &x, 1200);
createTrackbar("y", "Parameters", &y, 1200);
createTrackbar("radius", "Parameters", &radius, 900);
createTrackbar("dilate #", "Parameters", &iterations, 20);
std::string directory = "Secret";
std::string suffix = ".pgm";
Mat processedImage;
Mat origImg;
for (int fileCounter = 2; fileCounter < 3; fileCounter++) //1, 12
{
std::string numString = std::to_string(static_cast<long long>(fileCounter));
std::string imageFile = directory + numString + suffix;
testImage = imread(imageFile);
Mat bwImage;
cvtColor(testImage, bwImage, CV_BGR2GRAY);
GaussianBlur(bwImage, processedImage, Size(9, 9), 9);
threshold(processedImage, processedImage, 25, 255, THRESH_BINARY); //THRESH_OTSU
int numberContours = -1;
int iterations = 1;
imshow("Processed", processedImage);
}
vector<Vec3f> circles;
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
float dp2 = dp;
while (true)
{
float dp2 = dp;
Mat circleImage = processedImage.clone();
origImg = testImage.clone();
if (iterations > 0) dilate(circleImage, circleImage, element, Point(-1, -1), iterations);
Mat cannyImage;
Canny(circleImage, cannyImage, 100, 20);
imshow("Canny", cannyImage);
HoughCircles(circleImage, circles, HOUGH_GRADIENT, dp2/10, 5, houghParam1, houghParam2, 300, 5000);
cvtColor(circleImage, circleImage, CV_GRAY2BGR);
for (size_t i = 0; i < circles.size(); i++)
{
Scalar color = Scalar(0, 0, 255);
Point center2(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius2 = cvRound(circles[i][2]);
if (abs(center2.x - x) < 10 && abs((center2.y - y) < 10) && abs(radius - radius2) < 20) color = Scalar(0, 255, 0);
circle(circleImage, center2, 3, color, -1, 8, 0);
circle(circleImage, center2, radius2, color, 3, 8, 0);
circle(origImg, center2, 3, color, -1, 8, 0);
circle(origImg, center2, radius2,color, 3, 8, 0);
}
//Manual circles
circle(circleImage, Point(x, y), 3, Scalar(128, 0, 128), -1, 8, 0);
circle(circleImage, Point(x, y), radius, Scalar(128, 0, 128), 3, 8, 0);
circle(origImg, Point(x, y), 3, Scalar(128, 0, 128), -1, 8, 0);
circle(origImg, Point(x, y), radius, Scalar(128, 0, 128), 3, 8, 0);
imshow("Circles", circleImage);
imshow("Circled Orig", origImg);
int x = waitKey(50);
}
Mat drawnImage;
cvtColor(processedImage, drawnImage, CV_GRAY2BGR);
return 1;
}