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变换的步骤(执行过程):
  1. 在参数空间中建立一个二维(分别对应k,b)计数器,实际就是二维数组kbcnt,k维度为图像中直线斜率可能范围,b维度为图像中截距可能范围;数组中所有值都初始化为0;
  1. 扫描图像空间中的所有点(xi,yi),Hough变换式进行图像空间到参数空间的变换(ki,bi),计数kbcnt(ki,bi)++
  1. 设定阈值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中的阈值参数也应该细调。用上面程序对道路直线进行检测结果如下,
道路图片1
道路图片1
Canny算子边缘检测结果
Canny算子边缘检测结果
Hough直线检测结果
Hough直线检测结果
notion image
道路图片2
Canny算子边缘检测结果
Canny算子边缘检测结果
Hough直线检测结果
Hough直线检测结果

Hough变换源码分析

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