-
上一节中学习了霍夫变换的直线检测,本节则是学习霍夫变换的圆检测。
霍夫变换的圆检测的大致原理可以如图所示
即对于一副图像来说,我们认为其图像中的圆的半径大小已经确定,则我们对于图像中的每一个坐标点,我们以该点为圆心,以待求圆的半径为长度画圆,则最终几个圆之间可能会产生很多交点,我们选取相交点的数目最多的那个,即为待求圆的圆心。 -
OpenCv中霍夫变换圆检测的实现:
①因为霍夫圆检测对于噪声比较敏感,所以首先要对图像进行中值滤波
②基于效率考虑,OpenCv中实现的霍夫变换圆检测是基于图像梯度的实现,因此我们将其分为两部:
1.检测边缘,发现可能的圆心
2.基于第一步的基础上从候选圆心开始计算最佳半径的大小用到的相关API:
CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles, int method, double dp, double minDist, double param1 = 100, double param2 = 100, int minRadius = 0, int maxRadius = 0 );
第一个参数为输入的图像
第二个参数为输出的参数,即检测到图像中圆的信息
第三个参数为检测的方法,我们采用HOUGH_GRADIENT的方法即霍夫梯度
第四个参数为尺度,dip=1,在原图上寻找即让其为1,在原图的一半寻找让其为2
第五个参数为最短距离,是用来区分两个圆的
第六个参数为利用Canny来求梯度的低阈值
第七个参数为中心点累加的阈值(即以每个像素点为中心画圆所相交的点的强度)
第八个参数为最小半径
第九个参数为最大半径 -
代码
#include "stdafx.h" #include "iostream" #include "opencv2\opencv.hpp" using namespace std; using namespace cv; int main() { Mat src, dst; src = imread("G:/He/opencv_images/hough_circle_transform.jpg"); if (src.empty()) { cout << "could not load the images.." << endl; return -1; } namedWindow("original_images", CV_WINDOW_AUTOSIZE); namedWindow("test_images", CV_WINDOW_AUTOSIZE); Mat middle_filter; medianBlur(src,middle_filter, 3); imshow("original_images", src); cvtColor(middle_filter, middle_filter, CV_BGR2GRAY); vector<Vec3f>pcircles; HoughCircles(middle_filter, pcircles, CV_HOUGH_GRADIENT, 1, 10, 100, 30, 0, 50); src.copyTo(dst); for (size_t i = 0; i < pcircles.size(); i++) { Vec3f cc = pcircles[i]; circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(255, 0, 0), 2, LINE_AA); circle(dst, Point(cc[0], cc[1]), 2, Scalar(198, 23, 155), 2, LINE_AA); } imshow("test_images", dst); waitKey(0); destroyAllWindows(); return 0; }