今天有小伙伴提到直线检测,我便讲了霍夫变换,归纳分享下:
首先,介绍笛卡尔空间,就是我们常见的那个几何空间啦,通过 y=kx+b,可以表示直线。
然后,想一下,如果把上面方程变形一下,b=-xk+y,(k和b作为变量,xy作为常量),那么是不是又是一条另外的直线呢?对了,这就是霍夫空间了。
然后,你一不小心,发现两个规律:
①霍夫空间,笛卡尔空间中的直线,对应到霍夫空间中是一个点;
②笛卡尔空间中共线的点,在霍夫空间中对应的直线相交。(这个很重要,因为在笛卡尔空间中,我要做直线检测,岂不就是要找到最多的点所在的那条线嘛,我把所有的点都映射到霍夫空间中,找到最多的线公共交点就可以了。)
再然后,你会发现一个问题,如果是一条垂直于x轴的直线,那么k岂不是正无穷,怎么办?
没关系,引进极坐标表示直线:ρ=xCosθ+ySinθ(ρ为原点到直线的距离),如图所示:
再然后,就可以将笛卡尔空间和霍夫空间做映射了。
总结下上面的过程,如下图:
继续然后,上面红色字体:找到最多的线公共交点就可以了,怎么找?
哈哈,直接小白方式寻找,把霍夫空间网格化(就是一个很大的矩阵,初始值全是0),直线经过的地方标注1,没经过的地方还是0。再找出值最大的一些点就可以了。
好了,举个栗子:对一幅图像进行直线检验(如下图)
①对其进行边缘检测
②边缘检测后并二值化,就可以通过找非零点的坐标确定数据点
③对数据点进行霍夫变换,就形成了下面那个第三个图,好像一个水管,其实是很多很多曲线组成
④找出其中数值较大的一些点,通常可以给定一个阈值,Threshold一下,上面不是说了嘛,数值较大的点(我用红框框出来了)说明对应笛卡尔空间共线。
⑤最后得到那个有彩色直线的图,完成了直线检测。
上面的过程讲述原理,到此结束,算了,再举个栗子吧:
OK,这里Over了。
还要然后,这个怎么Coding啊?不急,直接OpenCV了。
C++的函数,直接调用就好:
void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )