从平面坐标到极坐标需要转换三个参数, C ( x 0 , y 0 , r ) C(x_0,y_0,r) C(x0,y0,r),其中 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)为圆心。
假设平面坐标中任意一个圆上的点,转换到极坐标中, C ( x 0 , y 0 , r ) C(x_0,y_0,r) C(x0,y0,r)处有最大值,霍夫变换基于此原理。
api:
InputArray: 输入图像,数据类型一般用Mat型即可,需要是8位单通道灰度图像
OutputArray:存储检测到的圆的输出矢量
method:使用的检测方法,目前opencv只有霍夫梯度法一种方法可用,该参数填HOUGH_GRADIENT即可(opencv 4.1.0下)
dp:double类型的dp,用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度。
minDist:为霍夫变换检测到的圆的圆心之间的最小距离
param1:它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半。
param2:也是第三个参数method设置的检测方法的对应的参数,对当前唯一的方法霍夫梯度法HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了。
minRadius:表示圆半径的最小值
maxRadius:表示圆半径的最大值
#include
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat img = imread("G:/testpic/img.png");
if (img.empty())
{
printf("cannot load the image");
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", img);
//均值滤波
Mat img_blur;
medianBlur(img, img_blur, 3);
imshow("blur", img_blur);
cvtColor(img_blur, gray, COLOR_BGR2GRAY);
//霍夫圆检测,必须为单通道灰度图
Mat dst;
img.copyTo(dst);
vector<Vec3f> pcircles;
HoughCircles(gray, pcircles, HOUGH_GRADIENT, 1, 50, 80, 80, 50, 200);
for (size_t i = 0; i < pcircles.size(); i++)
{
Vec3f cc = pcircles[i];
//画圆
circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0,0,255), 1, LINE_AA);
//画圆心
circle(dst, Point(cc[0], cc[1]), 2, Scalar(127,255,127), 1, LINE_AA);
}
imshow("output", dst);
waitKey(0);
return 0;
}