OpenCV图像处理篇之Hough变换
Last edited time
Sep 23, 2024 03:04 PM
AI summary
Hough变换用于将图像空间中的点集转换为参数空间,以便检测直线及其他形状。通过建立二维计数器并扫描图像中的所有点,可以识别共线点并确定直线。Hough变换支持极坐标表示,适用于检测直线、圆和椭圆等形状。OpenCV中提供了Hough变换的实现,用户需先进行边缘检测(如使用Canny算子),然后应用Hough变换以获得结果。
Tags
Hough Transform
Image Processing
OpenCV
Last edited by
图像空间到参数空间的转换
对于图像中共线的点集{(x0,y0), (x1,y1), …}都经过直线y=kx+b,先在我们换一个说法,“斜率为k,截距为b的直线y=kx+b包含了所有在该直线上的点”。一种强调的是图像中的点集,另一种强调的是直线的参数k和b,通过直线的点集去描述这条直线明显没有直接通过k,b两个参数去描述那样直接方便。而Hough变换就是将我们“点共线”的思维转化到参数空间{k,b}进行描述,图像空间中所有经过y=kx+b的点经过Hough变换后在参数空间都会相交于点(k,b),这样,通过Hough变换,就可以将图像空间中直线的检测转化为参数空间中对点的检测。我们不妨将y=kx+b进行一下变形:
这就是Hough变换将图像空间坐标(x,y)转化为参数空间(k,b)的Hough变换式。
Hough变换的步骤(执行过程):
- 在参数空间中建立一个二维(分别对应k,b)计数器,实际就是二维数组kbcnt,k维度为图像中直线斜率可能范围,b维度为图像中截距可能范围;数组中所有值都初始化为0;
- 扫描图像空间中的所有点(xi,yi),Hough变换式进行图像空间到参数空间的变换(ki,bi),计数kbcnt(ki,bi)++
- 设定阈值thr(图像中有多少个点共线才认为存在直线),kbcnt(ki,bi)>thr的ki,bi组成图像中的直线y=ki*x+bi
然而,上面的检测直线的方案貌似还有些问题:如果图像中存在竖直的直线呢,那kbcnt的k维度岂不是要无穷大!因此,才有了另一种参数空间的方案:利用极坐标参数而非“斜率-截距式”描述直线。

极坐标中的直线方程为
将其改写成Hough变换式,即自变量(x,y)到参数变量(r,theta)的映射:
使用极坐标参数空间,Hough变换的步骤不变,只不过将kbcnt替换成rthcnt,r范围是图像对角线的长度,th范围是0~2*pi。因为图像是离散的,所以r和th都有一个步进值dr和dth。
Hough变换除了检测直线,还可用来检测任何能用数学表达式表示的形状,如最常见的圆、椭圆,基本原理都是将图像空间的像素转变到参数空间,然后在参数空间中对共线/圆/椭圆的点进行统计,最后通过阈值判决是否是符合要求的形状。
http://en.wikipedia.org/wiki/Hough_transform 上对Hough变换的内容有更多的描述。
OpenCV中的Hough变换
在做Hough变换之前,一般都要先使用LOG或Canny先检测边缘,再对边缘图像进行Hough变换操作,上面程序使用Canny算子检测边缘,Canny算子
Canny(img, img, 100, 200, 3);
的两个阈值100,100选择很重要,间接影响Hough检测的结果,同时HoughLines
中的阈值参数也应该细调。用上面程序对道路直线进行检测结果如下,



道路图片2


Hough变换源码分析
Hough变换的源代码在
modules/imgproc/src/hough.cpp
中,提供了3种Hough变换源码:直线检测、概率Hough变换检测直线、圆检测,如果要实现其它有解析方程的图形的检测,则要自己动手写了。
先看Hough检测直线的代码,
cvHoughLines2
也只不过是个对不同Hough方法的封装,下面是该函数中的部分代码,选择不同的Hough变换方法,不妨详细看看标准Hough变换的实现代码,
Hough.cpp中对输出结构的定义为:
其它的Hough变换采用类似的方式逐层可以分析其源码,不妨自己试试?
Loading...