霍夫圆变换:霍夫圆变换的基本思路是认为图像上每一个非零像素点都有可能是一个潜在的圆上的一点,跟霍夫线变换一样,也是通过投票,生成累积坐标平面,设置一个累积权重来定位圆。
霍夫圆变换的原理
(1)从平面坐标到极坐标转换三个参数C(x,y,r)其中x,y是圆心坐标。
(2)假设平面坐标的任意一个圆上的点,转换到极坐标中C(x,y,r)处有最大值,霍夫变换正是利用这个原理实现圆的检测。
使用霍夫圆变换应该注意的问题:
(1)因为霍夫圆检测对噪声比较敏感,所以要先对图像做中值滤波。
(2)基于效率的考虑,OpenCV中实现霍夫变换圆检测是基于图像梯度的实现,分为两步,首先是检测边缘,发现可能的圆心,其次是基于第一步的基础上从候选圆心开始计算最佳半径大小。
HoughCircles参数说明
HoughCircles(
InputArray image, //输入图像,必须是8位的单通道灰度图像
OutputArray circles, //输出结果,发现圆的信息
Int method, //方法,HOUGH_GRADIENT
Double dp, //dp=1
Double mindist, //10,最短距离,可以分辨是两个圆的,否则认为是同心圆,
Double param1, //canny egde detection high threshold
Double param2, //中心累加器阈值-候选圆心
Int minradius, //最小半径
Int maxradius, //最大半径
)
代码测试如下
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace std;
using namespace cv;
int main()
{
//载入图片
Mat src,dst;
src=imread ("E://pictured//circle.jpg");
if (src.empty())
{
printf("could not load the picture...\n");
return -1;
}
char INPUT_TITLE[] = "input image";
char OUTPUT_TITLE[] = "hough circles image";
namedWindow(INPUT_TITLE,CV_WINDOW_AUTOSIZE);
namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
imshow(INPUT_TITLE,src);
//中值滤波
Mat m_output;
medianBlur(src,m_output,3);
cvtColor(m_output,m_output,CV_BGR2GRAY);
waitKey(0);
//霍夫圆检测
vector<Vec3f> circles;
HoughCircles(m_output,circles,CV_HOUGH_GRADIENT,1,10,100,30,100,300);
src.copyTo(dst);
for (size_t i=0;i<circles.size();i++)
{
Vec3f mt = circles[i];
circle(dst,Point(mt[0],mt[1]),mt[2],Scalar(0,0,255),2,LINE_AA);
circle(dst, Point(mt[0], mt[1]), 2, Scalar(90, 78, 255), 2, LINE_AA);
}
imshow(OUTPUT_TITLE,dst);
return 0;
}