OpenCV-Python快速入门(十五):霍夫变换
- 前言
- 前提条件
- 实验环境
- 霍夫变换
- 基本原理
- 霍夫直线变换(cv2.HoughLines())
- 概率霍夫变换(cv2.HoughLinesP())
- 霍夫圆变换(cv2.HoughCircles())
- 参考文献
前言
- 本文是个人快速入门OpenCV-Python的电子笔记,由于水平有限,难免出现错漏,敬请批评改正。
- 更多精彩内容,可点击进入OpenCV-Python快速入门专栏或我的个人主页查看
前提条件
- 熟悉Python
实验环境
- Python 3.x (面向对象的高级语言)
- OpenCV 4.0(python第三方库)
pip3 install opencv-python
霍夫变换
基本原理
- 以笛卡儿坐标系来引出霍夫变换基本原理。
- 笛卡儿空间中的一条直线在霍夫空间内的映射情况。
- 从上图可以看出,
- 笛卡儿空间内的一条直线确定了霍夫空间内的一个点。
- 霍夫空间内的一个点确定了笛卡儿空间内的一条直线。
- 笛卡儿空间中的一个点在霍夫空间内的映射情况。
- 从上图可以看出,
- 笛卡儿空间内的点映射到霍夫空间,就是直线。
- 霍夫空间内的直线映射到笛卡儿空间,就是点。
- 笛卡儿空间中的多个点映射到霍夫空间的情况。
- 从上面图片可以看出,在霍夫空间内,经过一个点的直线越多,说明其在笛卡儿空间内映射的直线,是由越多的点所构成(穿过)的。
- 两个点就能构成一条直线。但是,如果有一个点是因为计算错误而产生的,那么它和另外一个点,也会构成一条直线,此时就会凭空构造出一条实际上并不存在的直线。
- 这种情况是要极力避免的。因此,在计算中,我们希望用更多的点构造一条直线,以提高直线的可靠性。也就是说,如果一条直线是由越多点所构成的,那么它实际存在的可能性就越大,它的可靠性也就越高。因此,霍夫变换选择直线的基本思路是:选择有尽可能多直线交汇的点。
- 但是,笛卡儿空间有一定的局限性,在笛卡儿空间中,如下图所示情况,则无法映射到霍夫空间中,
- 此时,斜率 为无穷大,截距
- 为了解决上述问题,可以考虑将笛卡儿坐标系映射到极坐标系上,如下图所示。
- 在笛卡儿坐标系内使用的是斜率 和截距 ,即用表示一条直线。在极坐标系内,采用极径 (有时也用表示)和极角来表示,即来表示。
- 极坐标系中的直线可表示为: 即
- 上图的直线,可以使用极坐标的极径 和极角来表示。其中, 是直线 与图像原点 之间的距离,参数是直线 的直线 与
- 在这种表示方法中,图像中的直线有一个的角,而
- 与笛卡儿空间和霍夫空间的映射关系类似:
- 极坐标系内的一个点映射为霍夫坐标系(霍夫空间)内的一条线(曲线)。
- 极坐标系内的一条线映射为霍夫坐标系内的一个点。
- 一般来说,在极坐标系内的一条直线能够通过在霍夫坐标系内相交于一点的线的数量来评估。在霍夫坐标系内,经过一个点的线越多,说明其映射在极坐标系内的直线,是由越多的点所构成(穿过)的。因此,霍夫变换选择直线的基本思路是:选择由尽可能多条线汇成的点。通常情况下,设置一个阈值,当霍夫坐标系内交于某点的曲线达到了阈值,就认为在对应的极坐标系内存在(检测到)一条直线。
- 上述内容是霍夫变换的原理,即使完全不理解上述原理,也不影响我们使用 OpenCV 提供的霍夫变换函数来进行霍夫变换。OpenCV 给我们提供了接口(参数、返回值),我们只需要掌握接口的正确使用方法,就可以正确地处理图像问题,无须掌握其内部工作原理。
霍夫直线变换(cv2.HoughLines())
- OpenCV 提供了函数 cv2.HoughLines()用来实现霍夫直线变换,该函数要求所操作的源图像是一个二值图像,所以在进行霍夫变换之前要先将源图像进行二值化,或者进行 Canny 边缘检测。
概率霍夫变换(cv2.HoughLinesP())
- 概率霍夫变换对基本霍夫变换算法进行了一些修正,是霍夫变换算法的优化。它没有考虑所有的点。相反,它只需要一个足以进行线检测的随机点子集即可。
- 为了更好地判断直线(线段),概率霍夫变换算法还对选取直线的方法作了两点改进:
- 所接受直线的最小长度。如果有超过阈值个数的像素点构成了一条直线,但是这条直线很短,那么就不会接受该直线作为判断结果,而认为这条直线仅仅是图像中的若干个像素点恰好随机构成了一种算法上的直线关系而已,实际上原图中并不存在这条直线。
- 接受直线时允许的最大像素点间距。如果有超过阈值个数的像素点构成了一条直线,但是这组像素点之间的距离都很远,就不会接受该直线作为判断结果,而认为这条直线仅仅是图像中的若干个像素点恰好随机构成了一种算法上的直线关系而已,实际上原始图像中并不存在这条直线。
- OpenCV 提供了函数 cv2.HoughLinesP()用来实现概率霍夫变换。
霍夫圆变换(cv2.HoughCircles())
- 霍夫变换除了用来检测直线外,也能用来检测其他几何对象。实际上,只要是能够用一个参数方程表示的对象,都适合用霍夫变换来检测。
- 用霍夫圆变换来检测图像中的圆,与使用霍夫直线变换检测直线的原理类似。在霍夫圆变换中,需要考虑圆半径和圆心(x 坐标、y 坐标)共 3 个参数。在 OpenCV 中,采用的策略是两轮筛选。第 1 轮筛选找出可能存在圆的位置(圆心);第 2 轮再根据第 1 轮的结果筛选出半径大小。
- 与用来决定是否接受直线的两个参数“接受直线的最小长度(minLineLength)”和“接受直线时允许的最大像素点间距(MaxLineGap)”类似,霍夫圆变换也有几个用于决定是否接受圆的参数:圆心间的最小距离、圆的最小半径、圆的最大半径。
- OpenCV 中,函数 cv2.HoughCircles()用来实现霍夫圆变换,该函数将 Canny 边缘检测和霍夫变换结合。
参考文献
[1] https://opencv.org/
[2] 李立宗. OpenCV轻松入门:面向Python. 北京: 电子工业出版社,2019