霍夫变换
简介:
霍夫变换(Hough Transform)于1962年由Paul Hough 首次提出,后于1972年由Richard Duda和Peter Hart推广使用,是图像处理领域内从图像中检测几何形状的基本方法之一。经典霍夫变换用来检测图像中的直线,后来霍夫变换经过扩展可以进行任意形状物体的识别,例如圆和椭圆。
由于霍夫变换涉及的数学知识较为复杂,如有需要深入理解的,可以参考一下Opencv官方网站。这里为了方便理解,我简述一下自己的理解:
霍夫直线变换:
在二维x-y空间中,直线可以由 y=kx+b(k为斜率,b为直线与y轴的截距)来表示。 也就是说,已知某一点A(x0,y0),则可以确定过该点的直线簇。
若我们把方程改写成:b=-kx+y。而在参数空间中,b=-kx0+y0就表示一条直线。
不难看出,x-y空间中的直线和参数空间k-b中的点一一对应。
假如二维x-y空间上存在若干个在同一条直线y=k0x+b0上的点,
则表示在参数空间k-b上(k!=k0.b!=b=)上为若干条平行的直线。
而当我们用极坐标表示时,如下图:
可知,当二维空间x-y的点在同一条直线上时,其体现在极坐标空间时有集中在一个点上的特点。依据此特点我们就可以用算法实现霍夫直线变换。
实现函数:标准霍夫直线变换HoughLines()和渐进概率式霍夫直线变换HoughLinesP()函数
标准霍夫直线变换(HoughLines()函数):由于输出为极坐标,初学者较难使用,我们在这里暂时不展开说明。
渐进概率式霍夫直线变换(HoughLinesP()函数):
部分代码展示:
int main()
{
Mat src, gray_src, dest;
src = imread("C:/Users/86159/Desktop/pp.png");
Canny(src, gray_src, 100, 200, 3); //Canny算子检测边缘转化为二值图像
vector<Vec4f>plines;
Mat dst = ~Mat::zeros(src.size(), CV_8UC3);
HoughLinesP(gray_src, plines, 1, CV_PI / 180.0, 10, 0, 20); /*霍夫直线检测*/
for (size_t i = 0; i < plines.size(); i++)
{
Vec4f hl = plines[i];
line(dst, Point(hl[0], hl[1]), Point(hl[2], hl[3]), Scalar(0, 0, 0), 1, LINE_AA); //绘制直线
}
namedWindow("效果图", WINDOW_NORMAL);
resizeWindow("效果图", 400, 400);
moveWindow("效果图", 800, 0);
imshow("效果图", dst);
waitKey(0);
return 0;
}
==特别提醒:==霍夫直线变换中 HoughLinesP()函数的输入参数必须为二值图像。
效果如下:
霍夫圆变换:
圆可以用(a,b,r)来表示,所以当检测某一半径的圆的时候,可以选择与原图像空间同样的空间作为参数空间。那么圆图像空间中的一个圆对应了参数空间中的一个点,参数空间中的一个点对应了图像空间中的一个圆,圆图像空间中在同一个圆上的点,它们的参数相同即a,b相同,那么它们在参数空间中的对应的圆就会过同一个点(a,b),所以,将原图像空间中的所有点变换到参数空间后,根据参数空间中点的聚集程度就可以判断出图像空间中有没有近似于圆的图形。
部分代码展示:
Mat src, gray_src, dest;
src = imread("C:/Users/86159/Desktop/pp.png");
medianBlur(src, dest, 3); //中值滤波,防止椒盐噪声干扰
cvtColor(dest, dest, COLOR_BGR2GRAY); //转换为灰度图像
vector<Vec3f> pcircles;
Mat dst = ~Mat::zeros(src.size(), CV_8UC3);
HoughCircles(dest, pcircles, HOUGH_GRADIENT, 1, 100, 100, 30, 50, 500); //霍夫圆变换
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), 5, LINE_AA);
circle(dst, Point(cc[0], cc[1]), 12, Scalar(0, 255, 0), -1, LINE_AA);
}
效果如下
希望对读者有所帮助,喜欢的话可以关注一下我的公众号,我会把学习笔记发在上面,大家可以一起共同学习!