霍夫圆检测的基本原理与霍夫线变换原理类似,直线检测中的点对应极坐标空间,在变换中被三维空间中圆坐标空间代替。对直线而言,一条直线可由极坐标参数来确定,而对于圆来说,就需要三个参数来确定一个圆。同二维霍夫线变换原理,三维空间曲线中相交于一点的边缘点集越多,那么它们经过的共同圆上的像素点就越多,设定阈值进行相应判断一个圆是否被检测到,这就是标准霍夫圆变换的原理。但也正是由于三维空间的计算量大大增加的原因,标准霍夫圆变换很难被应用到实践中,从平面计算到三维空间变换,增加了相应的计算复杂度,opencv提供了根据霍夫圆变换改进的霍夫梯度法来实现相关圆检测算法。
霍夫梯度法的依据是圆心一定出现在圆上的每个点的模向量上,圆上点的模向量交点就是圆心的所在位置。霍夫梯度法的第一步就是找到这些圆心,这样三维的累加平面就转化为二维累加平面;第二步是根据所有候选中心的边缘非零像素对其的支持程度来确定程度来确定半径。
霍夫梯度法的实现首先利用Canny边缘检测,对边缘中的非零点,根据Sobel的水平与垂直方向计算其局部梯度;然后对线上像素点进行累计,标记边缘图像中非零像素点的位置;其次通过累加器中的点集来计算其候选的中心,中心需要满足给定阈值及邻域距离;最后对像素中心距离排序,对候选中心进行边缘图像非零像素验证和候选中心距离验证。
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
int main(int argc,char ** argv)
{
cv::Mat srcImage = imread();
cv::imshow("srcImage",srcImage);
cv::Mat src_gray;
cvtColor(srcImage,src_gray,CV_BGR2GRAY);
GaussianBlur(src_gray,src_gray,Size(9,9),2,2);
vector<vec3f> circles;
HoughCircles(src_gray,circles,CV_HOUGH_GRADIENT,1,src_gray.rows/8,200,100,0,0);
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]);
ciecles(srcImage,center,3,Scalar(0,255,0),-1,8,0);
}
cv::imshow("HoughResult",srcImage);
cv::waitKey(0);
return 0;
}