近日遇到一个需求,要从点云数据中提取空间平面。看了看计算机图形学中关于直线检测的霍夫变换的原理,自己写了一个用于三维空间点中进行平面检测的霍夫变换算法。
先说从最简单的,xy平面图像中,提取直线的霍夫变换开始。
假如xy平面上存在一条直线,用方程y=kx+b来表示。那么在kb平面上就可以用一个点(k,b)来对应xy平面上的这条直线。这个变换可以反过来,已知xy平面上有一个点(x0,y0),所有过该点的直线都肯定满足:y0=k·x0+b。改写一下就是:b= x0·k + y0,在kb平面上是一条直线。
假如xy平面上存在一系列的点P1,P2,...构成一条直线,那么对每一个点都进行霍夫变换,最终会在kb平面上得到一个直线族,直线族相交于一点(k0,b0),就是所要寻找的直线y=k0·x+b0。
上述算法原理上可行,但是实际中有两个严重问题:1 平行与y轴的直线斜率k不存在;2 k、b的取值范围都是(-∞,+∞),编程中不可能接受这么大的平面。
因此直线检测的霍夫变换用的是法线式直线方程:p=x·cosθ+y·sinθ。θ是法线角度,p是直线到原点距离。很明显的,θ∈(0,π), p∈(-Max(|P1,P2,...|),Max(|P1,P2,...|)),在给定一堆点坐标的前提下,这两个参数都是有界的。
最终,为了检测出直角坐标X-Y中由点所构成的直线,将p-θ平面分割为许多小格。根据直角坐标中每个点的坐标(x,y),在θ∈ (0,π)范围内内以小格的步长计算各个p值,所得值落在某个小格内,便使该小格的累加记数器加1。当直角坐标中全部的点都变换后,对小格进行检验,计数值最大的小格,其(θ,p)值对应于直角坐标中所求直线。
理解直线检测的原理之后,就可以推广到三维空间平面检测。关键在于寻找合适的平面方程形式,让方程参数取值范围有明确的边界。参考法线式直线方程,这里我选择用点法式平面方程:xsinθcosφ+ysinθsinφ+zcosθ=r。其中r为原点到平面距离,θ为平面法向量天顶角,φ为平面法向量方位角,上述概念不清楚的话可以去参考球坐标系。
对于给定的一系列XYZ空间点(P1,P2,...),很明显,θ∈(0,π),φ∈(-π,+π),r∈(0,Max(|P1,P2,...|)),我们可以确定一个有界三维霍夫空间(θ,φ,r),把该空间细分为许多小格子。对于每一个空间点坐标(x0,y0,z0),按照θ∈(0,π),φ∈(-π,+π)的取值范围去遍历计算r = x0·sinθcosφ+y0·sinθsinφ+z0·cosθ,所得值落在某个小格内,便使该小格的累加记数器加1。完成全部霍夫变换后,取计数值最大的小格,对应的(θ,φ,r)值就可以得到XYZ空间内的平面。