基于局部表面拟合的方法进行法向量估计:点云的采样表面处处光滑的情况下,任何点的局部邻域都可以用平面进行很好的拟合;为此,对于点云中的每个扫描点
p
p
p,搜索到与其最近邻的
K
K
K个相邻点,然后计算这些点最小二乘意义上的局部平面
P
P
P,此平面可以表示为:
P
(
n
⃗
,
d
)
=
arg min
(
n
⃗
,
d
)
∑
i
=
1
k
(
n
⃗
⋅
p
i
−
d
)
2
(1)
P(\vec{n},d)=\argmin \limits_{(\vec{n},d)} \sum_{i=1}^k\ (\vec{n}\cdot p_i-d)^2\tag{1}
P(n,d)=(n,d)argmini=1∑k(n⋅pi−d)2(1) 式中,
n
⃗
\vec{n}
n为平面
P
P
P的法向量,
d
d
d为
P
P
P到坐标原点的距离。 可以认为由
K
K
K个最近点拟合出的平面的法向量即当前扫描点的法向量。平面
P
P
P的法向量可以由主成分分析(PCA)得到,由运算知
P
P
P经过其
K
K
K邻域点的质心
P
0
P_0
P0,且法向量
n
⃗
\vec{n}
n满足
∣
∣
n
⃗
∣
∣
=
1
||\vec{n}||=1
∣∣n∣∣=1,先对式(2)中的协方差矩阵
M
M
M进行特征值分解,求得
M
M
M的各特征值,
M
M
M的最小特征值所对应的特征向量即
P
P
P的法向量。
M
=
1
k
∑
i
=
1
k
(
p
i
−
p
0
)
(
p
i
−
p
0
)
T
(2)
M=\frac{1}{k}\sum_{i=1}^k\ ( p_i-p_0)( p_i-p_0)^T\tag{2}
M=k1i=1∑k(pi−p0)(pi−p0)T(2)
2、法向量定向
前面计算出的法向量具有二义性,即只是得到了法向量所在的直线,而没有确定以直线的那个方向为法向量的最终方向。用以下方法对求出的法向量进行重定向: 假设点云足够稠密且采样平面处处光滑,那么相邻两点的法向量会接近于平行。令
n
i
⃗
、
n
j
⃗
\vec{n_i}、\vec{n_j}
ni、nj为相邻两点
x
i
、
x
j
{x_i}、{x_j}
xi、xj的法向量,如果法向量的方向是一致的,那么
n
i
⃗
⋅
n
j
⃗
≈
1
\vec{n_i}\cdot\vec{n_j}\approx1
ni⋅nj≈1若此内积为负,则说明其中某个点的法向量需要被翻转。因此,首先为点云中某个点设定一个法向量朝向,然后遍历其他所有点,若当前点法向量设定为
n
i
⃗
,
n
j
⃗
\vec{n_i},\vec{n_j}
ni,nj为下一个要遍历的点,如果
n
i
⃗
⋅
n
j
⃗
<
0
\vec{n_i}\cdot\vec{n_j}<0
ni⋅nj<0则将
n
j
⃗
\vec{n_j}
nj翻转,否则保持不变。
3、表面曲率
对式(2)中的协方差矩阵
M
M
M进行特征值分解,求得
M
M
M的各特征值,若特征值满足
λ
0
≤
λ
1
≤
λ
2
\lambda_0\leq\lambda_1\leq\lambda_2
λ0≤λ1≤λ2,则
P
P
P点的表面曲率为:
δ
=
λ
0
λ
0
+
λ
1
+
λ
2
(3)
\delta=\frac{\lambda_0}{\lambda_0+\lambda_1+\lambda_2}\tag{3}
δ=λ0+λ1+λ2λ0(3)
δ
\delta
δ越小表明邻域越平坦,
δ
\delta
δ越大则表明邻域的起伏变化越大。
A
,
B
,
C
A,B,C
A,B,C表示坐标值,
A
i
,
B
i
,
C
I
A_i,B_i,C_I
Ai,Bi,CI表示向量,以
O
A
→
\overrightarrow{OA}
OA 作为正方向,由于
A
A
A点法向量已经定向,所以
A
A
A点法向量为:
A
i
→
\overrightarrow{A_i}
Ai=(0,0,1),对
B
B
B点的法向量进行法向量方向的确定: 其中,
B
B
B点的法向量坐标为:
B
i
1
→
=
(
1
2
,
0
,
1
2
)
\overrightarrow{B_{i1}}=(\frac{1}{\sqrt{2}},0,\frac{1}{\sqrt{2}})
Bi1=(21,0,21),
B
i
2
→
=
(
1
2
,
0
,
−
1
2
)
\overrightarrow{B_{i2}}=(\frac{1}{\sqrt{2}},0,-\frac{1}{\sqrt{2}})
Bi2=(21,0,−21);(可以看出
B
i
→
\overrightarrow{B_i}
Bi 的方向与
O
A
→
\overrightarrow{OA}
OA 同向,定向的目的就是找出与
O
A
→
\overrightarrow{OA}
OA同向的
B
i
→
\overrightarrow{B_i}
Bi ),其理论依据为:
A
i
→
⋅
B
i
→
>
0
(4)
\overrightarrow{A_i}\cdot \overrightarrow{B_i}>0\tag{4}
Ai⋅Bi>0(4) 所谓的调整方向就是:上式中计算,你带入的
B
i
→
\overrightarrow{B_i}
Bi 值为
B
i
2
→
\overrightarrow{B_{i2}}
Bi2时,对
B
i
2
→
\overrightarrow{B_{i2}}
Bi2进行操作使
B
i
2
→
\overrightarrow{B_{i2}}
Bi2=
B
i
1
→
\overrightarrow{B_{i1}}
Bi1。 实际操作中,以
A
A
A点作为视点,求出:
B
i
→
⋅
(
A
−
B
)
>
0
\overrightarrow{B_i}\cdot \ (A-B)>0
Bi⋅(A−B)>0时的
B
i
→
\overrightarrow{B_i}
Bi即为
B
B
B点与视点
A
A
A同向的法向量。 综上所述:所谓的定向就是以其中一点
N
i
N_i
Ni的法向量方向作为正方向,其邻域内所有点的法向量
N
j
N_j
Nj满足:
N
j
⋅
N
i
>
0
(5)
{N_j}\cdot {N_i}>0\tag{5}
Nj⋅Ni>0(5)
6、CloudCompare
CloudCompare软件中也有计算法向量的功能,这里给出具体操作。
Normals > Compute:计算所选实体的法线 Normals > Invert:反转所选实体的法线 Normals > Orient Normals > With Minimum Spanning Tree:用同样的方法重新定位点云的全部法线(最小生成树) Normals > Orient Normals > With Fast Marching:用同样的方法重新定位点云的全部法线(快速行进法) Normals > Convert to > HSV:将云的法线转换到 HSV 颜色字段 Normals > Convert to > Dip and Dip direction SFs:转换点云的法线到两个标量域 Normals > Clear:为选定的实体移除法线
已知视点为
V
p
V_p
Vp,任意一点的坐标为
P
i
P_i
Pi,法向量为
n
i
⃗
\vec{n_i}
ni。对所有法向量
n
i
⃗
\vec{n_i}
ni定向使它们朝向视点方向,需满足如下公式:
n
i
⃗
⋅
(
V
p
−
P
i
)
>
0
\vec{n_i}\cdot(V_p-P_i)>0
ni⋅(Vp−Pi)>0 代码中的setViewPoint(0,0,0)就是用来进行视点设置的: