霍夫梯度法原理如下:首先对图像应用canny边缘检测,然后对边缘图像中每一个非0点,考虑其局部梯度,通过sobel计算。利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加,同时,标记边缘图像中每一个非0像素的位置。然后从累加器中这些点中选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻。这些候选的中心按照累加值降序排列,以便于最支持像素的中心首先出现。接下来对每一个中心,考虑所有的非0像素。这些像素按照其与中心的距离排序。从到最大半径的最小距离算起,选择非0像素最支持的一条半径。如果一个中心受到边缘图像非0像素最充分的支持,并且到前期被选择的中心有足够的距离,它将会被保留。这个实现可以使算法执行起来更快,能够帮助解决三维累加器中其他稀疏分布问题。
void HoughCircles(
InputArray image,//输入图像8位
OutputArray circles,//数组或存储器
int method, //CV_HOUGH_GRADIENT 目前只有梯度法
double dp, //累加器图像分辨率 ≥1
double minDist,//不同圆之间最小距离
double param1=100, //canny上限阈值,下限阈值=上限阈值/2cvCanny( img, edges, MAX(canny_threshold/2,1), canny_threshold, 3 );</span>
double param2=100,//累加器阈值
int minRadius=0, //最小圆半径
int maxRadius=0 //最大圆半径
);
cvCircle(
CvArr* img, //输入图像
CvPoint center, //圆心
int radius,//半径
CvScalar color, //颜色
int thickness CV_DEFAULT(1),//粗细
int line_type CV_DEFAULT(8),
int shift CV_DEFAULT(0)//0
);
样图:圆直径依次为 80,90,100,110,120
未经平滑处理结果:cvcircle绘制时,半径与圆心损失精度
经平滑处理结果:cvcircle绘制时,半径与圆心损失精度
using namespace cv; int main() { IplImage* img = cvLoadImage("correct_Img_1.jpg",0);//转为灰度图 cvSmooth( img, img, CV_GAUSSIAN, 5, 5);//平滑处理 vector<Vec3f> circles; HoughCircles( (Mat)img, circles, CV_HOUGH_GRADIENT, 1.5 ,10, 80, 110, 35 ,65);//hough圆变换 //img = cvLoadImage("correct_Img_1.jpg",1); for (int i = 0; i < circles.size(); i++) { CvPoint center;//圆心 center.x = circles[i][0]; center.y = circles[i][1]; int radius = circles[i][2];//半径 cvCircle( img, center, radius, Scalar(0,255,0), 1, 8, 0);//绘制圆 cvCircle( img, center, 3, Scalar(0,255,0), 3, 8, 0);//绘制圆心 std::cout<<"圆心为:"<<circles[i][0]<<","<<circles[i][1]<<" 直径为:"<<2*circles[i][2]<<"\n";//为了保证精度,以原值输出 } cvSaveImage("out.jpg",img); cvNamedWindow("hough圆检测",1); cvShowImage("hough圆检测",img); cvWaitKey(0); cvReleaseImage(&img); cvDestroyWindow("hough圆检测"); return 0; }