文章目录
一、前言
笔者最近在做的一个项目是要从点云中提取特征(边缘、角点)。点云的来源是双目结构光相机,尽管工业级的双目结构光相机已经有了比较高的精度(名义z轴精度为0.5mm),但实际测量误差有时甚至能到2mm,为了能获得更鲁棒和准确的结果还需要尽可能的减小噪声,因此对点云滤波方法进行学习。
![](https://i-blog.csdnimg.cn/blog_migrate/15a0e6802bba8b015f6646a4961f4fd6.png#pic_center)
![](https://i-blog.csdnimg.cn/blog_migrate/c5754b4b829d7b848ecf5bde3e79f0fe.png#pic_center)
这里有一篇点云滤波综述[1],我将选出一些经典的方法进行学习,并将笔记分享出来,欢迎交流。
参考的资料是Survey of Methods in Computer Graphics (600.658)课件以及最初论文
这次的笔记记录的是MLS,论文原文[2]。实话说我没有搞清楚这个命名到底是怎么回事,这篇论文的缩写是PSS(Point Set Surfaces),论文里用到的数学工具是MLS。所以我看网上讨论这种方法时候,用这两个名称的都有。
二、前置知识
2.1 小引理
- 极值点的判断条件:
如果给定一个方程 F : R 3 → R F:\mathbb{R}^3\to\mathbb{R} F:R3→R, p ∈ R 3 p \in \mathbb{R}^3 p∈R3是 F F F的极值点当且仅当 F F F 在 p p p 点的梯度为0,即 ∇ F ∣ p = 0 \nabla F|p=0 ∇F∣p=0。 - 几种内积的梯度(后边会用到)
F : R 3 → R F:\mathbb{R}^3\to\mathbb{R} F:R3→R 满足如下形式, F ( p ) = ⟨ p , q ⟩ F(p)=\langle p, q\rangle F(p)=⟨p,q⟩, ∇ F ∣ p = q \nabla F|_p=q ∇F∣p=q
F : R 3 → R F:\mathbb{R}^3\to\mathbb{R} F:R3→R 满足如下形式, F ( p ) = ⟨ p , q ⟩ n F(p)=\langle p, q\rangle ^n F(p)=⟨p,q⟩n, ∇ F ∣ p = n ⟨ p , q ⟩ n − 1 q \nabla F|_p=n\langle p,q\rangle ^{n-1}q ∇F∣p=n⟨p,q⟩n−1q
F : R 3 → R F:\mathbb{R}^3\to\mathbb{R} F:R3→R 满足如下形式, F ( p ) = ⟨ p , p ⟩ F(p)=\langle p, p\rangle F(p)=⟨p,p⟩, ∇ F ∣ p = 2 p \nabla F|_p=2p ∇F∣p=2p
F : R 3 → R F:\mathbb{R}^3\to\mathbb{R} F:R3→R 满足如下形式, F ( p ) = ⟨ p , M p ⟩ F(p)=\langle p, Mp\rangle F(p)=⟨p,Mp⟩, ∇ F ∣ p = ( M T + M ) p \nabla F|_p=(M^T+M)p ∇F∣p=(MT+M)p
但其实雅可比矩阵有行形式跟列形式,不同形式之间的结果差了个转置。 - 二元二次多项式的一般形式
F ( x , y ) = c 00 + c 10 x + c 01 y + c 11 x y + c 20 x 2 + c 02 y 2 F(x,y)=c_{00}+c_{10}x+c_{01}y+c_{11}xy+c_{20}x^2+c_{02}y^2 F(x,y)=c00+c10x+c01y+c11xy+c20x2+c02y2
可以将其改写成内积形式:
F ( x , y ) = ⟨ v , Q ( x , y ) ⟩ v = ( c 00 , c 10 , c 01 , c 11 , c 20 , c 02 ) T Q ( x , y ) = ( 1 , x , y , x y , x 2 , y 2 ) T F(x,y)=\langle v, Q(x,y)\rangle \\ v=(c_{00},c_{10},c_{01},c_{11},c_{20},c_{02})^T \\ Q(x,y) = (1,x,y,xy,x^2,y^2)^T F(x,y)=⟨v,Q(x,y)⟩v=(c00,c10,c01,c11,c20,c02)TQ(x,y)=(1,x,y,xy,x2,y2)T - 拉格朗日乘数定理(用来求解有约束条件下的极值问题)
满足 G ( p ) = c G(p)=c G(p)=c约束条件下 F F F的极值点 p p p,一定满足 ∇ F ∣ p = λ ∇ G ∣ p \nabla F|_p=\lambda\nabla G|_p ∇F∣p=λ∇G∣p,可以简单记作有约束目标函数的极值点在约束表面上的变化率为零(这地方没理解透彻啊) - Lagrangians and Symmetric Matrices
如果 M M M是一个对称矩阵, F ( p ) = ⟨ p , M p ⟩ s . t . ∣ ∣ p ∣ ∣ 2 = 1 F(p)=\langle p,Mp\rangle \ \ \ s.t. \ ||p||^2=1 F(p)=⟨p,Mp⟩ s.t. ∣∣p∣∣2=1,那么 p p p是 F ( p ) F(p) F(p)的极值点当且仅当 p p p是 M M M的特征向量
∇ F ∣ p = M T p + M p = 2 M p = λ G ∣ p = λ 2 p ∴ M p = λ p \nabla F|_p=M^Tp+Mp=2Mp=\lambda G|_p =\lambda2p \\ \therefore Mp = \lambda p ∇F∣p=MTp+Mp=2Mp=λG∣p=λ2p∴Mp=λp
2.2 线性最小二乘法
通常用于在给定数据的情况下,找到一个最佳的线性模型来拟合数据。
2.2.1 A x = b Ax=b Ax=b 形式
假设有这样一些数据点
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
…
,
(
x
n
,
y
n
)
}
\{(x_1,y_1), (x_2,y_2), \dots ,(x_n,y_n)\}
{(x1,y1),(x2,y2),…,(xn,yn)},希望能找到
y
=
k
x
+
b
y=kx+b
y=kx+b 这样的模型来拟合这些数据。改写成矩阵形式:
(
x
1
1
x
2
1
⋮
⋮
x
n
1
)
(
k
b
)
=
(
y
1
y
2
⋮
y
n
)
\begin{pmatrix} x_1 & 1\\x_2 & 1\\\vdots & \vdots \\x_n & 1\end{pmatrix} \begin{pmatrix}k\\b\end{pmatrix}=\begin{pmatrix} y_1\\y_2\\\vdots\\y_n\end{pmatrix}
x1x2⋮xn11⋮1
(kb)=
y1y2⋮yn
使用
A
x
=
b
Ax=b
Ax=b来代替上边的三个矩阵,由于有噪声的存在,线性方程组的系数矩阵的秩应该小于增广矩阵的秩?(可以这样说么),可能没有精确解,所以使用最小二乘法来求解近似解。
一个最直观的想法是使得残差平方和最小:
m
i
n
ε
=
∥
A
x
−
b
∥
2
2
=
(
A
x
−
b
)
T
(
A
x
−
b
)
=
x
T
A
T
A
x
−
2
x
T
A
T
b
+
b
T
b
\begin{align} min\ \varepsilon&=\left\| \mathbf{Ax-b} \right\|_2^2 \\ &= (Ax-b)^T(Ax-b)\\ &=x^TA^TAx-2x^TA^Tb+b^Tb \end{align}
min ε=∥Ax−b∥22=(Ax−b)T(Ax−b)=xTATAx−2xTATb+bTb
为求出最小值,令
ε
\varepsilon
ε对
x
x
x的导数为零
∂
ε
∂
x
=
2
A
T
A
x
−
2
A
T
b
=
0
⟹
x
=
(
A
T
A
)
−
1
A
T
b
\frac{\partial \varepsilon}{\partial x}=2A^TAx-2A^Tb=0\Longrightarrow x=(A^TA)^{-1}A^Tb
∂x∂ε=2ATAx−2ATb=0⟹x=(ATA)−1ATb
还有一种是通过投影来理解最小二乘,感兴趣可以查一下,更加直观
2.2.2 A x = 0 Ax=0 Ax=0形式
超定方程的求解、最小二乘解、Ax=0、Ax=b的解,求解齐次方程组,求解非齐次方程组(推导十分详细)
三、MLS(移动最小二乘)
3.1 原理
LS直接生成一个全局模型来拟合所有数据点,因此拟合结果容易被离群值拉偏。
而MLS会对每个预测点的局部区域拟合出一个模型,局部区域中的点对于模型的贡献取决于其与预测点之间的距离。移动二字也体现在这里,即通过一个移动窗口来逐点拟合。
在每一个点
p
p
p,找到一个函数
ϕ
p
\phi_p
ϕp使得
E
(
ϕ
p
)
=
Σ
i
Θ
(
∥
p
i
−
p
∥
2
)
(
ϕ
p
(
p
i
)
−
ϕ
i
)
2
E(\phi_p)=\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)(\phi_p(p_i)-\phi_i)^2
E(ϕp)=ΣiΘ(∥pi−p∥2)(ϕp(pi)−ϕi)2
i
i
i 是点
p
p
p 邻域的序号,
Θ
\Theta
Θ是一个权重函数,它的函数值随自变量的减小而增大,通常使用指数函数来表示,下面举两个例子。
- 当
ϕ
p
(
)
\phi_p()
ϕp()表示常值函数时,可以发现MLS的结果是以距离为权重的加权平均和
E ( ϕ p ) = Σ i Θ ( ∥ p i − p ∥ 2 ) ( ϕ p − ϕ i ) 2 E(\phi_p)=\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)(\phi_p-\phi_i)^2 E(ϕp)=ΣiΘ(∥pi−p∥2)(ϕp−ϕi)2
求梯度并令其等于零,可以求得使得 E E E最小的 ϕ p \phi_p ϕp
∂ E ∂ ϕ p = Σ i Θ ( ∥ p i − p ∥ 2 ) 2 ( ϕ p − ϕ i ) = 0 ⟹ ϕ p = Σ i Θ ( ∥ p i − p ∥ ) ϕ i Σ i Θ ( ∥ p i − p ∥ ) \frac{\partial E}{\partial \phi_p}=\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)2(\phi_p-\phi_i)=0\\\Longrightarrow \phi_p=\frac{\Sigma_i\Theta(\left\|\mathbf{p_i-p}\right\|)\phi_i}{\Sigma_i\Theta(\left\|\mathbf{p_i-p}\right\|)} ∂ϕp∂E=ΣiΘ(∥pi−p∥2)2(ϕp−ϕi)=0⟹ϕp=ΣiΘ(∥pi−p∥)ΣiΘ(∥pi−p∥)ϕi
这个结果看着非常亲切对吧,其实就是在做高斯滤波 - 当
ϕ
p
(
)
\phi_p()
ϕp()为二次多项式时候
E ( ϕ p ) = Σ i Θ ( ∥ p i − p ∥ 2 ) ( ⟨ ϕ p , Q ( p i ) ⟩ − ϕ i ) 2 E(\phi_p)=\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)(\langle\phi_p,Q(p_i)\rangle-\phi_i)^2 E(ϕp)=ΣiΘ(∥pi−p∥2)(⟨ϕp,Q(pi)⟩−ϕi)2
对于 p ∈ R 2 p\in\mathbb{R}^2 p∈R2的情况, Q ( p i ) = ( 1 , x i , y i , x i y i , x i 2 , y i 2 ) T Q(p_i)=(1,x_i,y_i,x_iy_i,x_i^2,y_i^2)^T Q(pi)=(1,xi,yi,xiyi,xi2,yi2)T, ϕ p \phi_p ϕp为 ϕ p ( ) \phi_p() ϕp()各项的系数 ( c 00 , c 10 , c 01 , c 11 , c 20 , c 02 ) T (c_{00},c_{10},c_{01},c_{11},c_{20},c_{02})^T (c00,c10,c01,c11,c20,c02)T
∂ E ∂ ϕ p = Σ i Θ ( ∥ p i − p ∥ 2 ) 2 ( ⟨ ϕ p , Q ( p i ) ⟩ − ϕ i ) Q ( p i ) = 0 ⟹ ϕ p = ( Σ i Θ ( ∥ p i − p ∥ 2 ) Q ( p i ) Q ( p i ) T ) − 1 ( Σ i Θ ( ∥ p i − p ∥ 2 ) ϕ i Q ( p i ) ) \frac{\partial E}{\partial \phi_p}=\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)2(\langle\phi_p,Q(p_i)\rangle-\phi_i)Q(p_i)=0\\ \Longrightarrow\phi_p=(\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)Q(p_i)Q(p_i)^T)^{-1}(\Sigma_i\Theta(\left\| \mathbf{p_i-p} \right\|_2)\phi_iQ(p_i)) ∂ϕp∂E=ΣiΘ(∥pi−p∥2)2(⟨ϕp,Q(pi)⟩−ϕi)Q(pi)=0⟹ϕp=(ΣiΘ(∥pi−p∥2)Q(pi)Q(pi)T)−1(ΣiΘ(∥pi−p∥2)ϕiQ(pi)) - 这个方法也可以拓展到任意维度的方程以及任意次数的多项式。
3.2 回到论文
那么面对实际的点云数据,要怎么使用MLS进行点云滤波呢。下面用几幅图来简单描述下MLS的想法(图片截自上交应忍冬老师的课件)
- 对查询点的邻域拟合一条多项式曲面(在图中是条曲线)
- 移动查询点到曲面上,实现滤波
但这时候问题来了,以什么方向移动到曲面上是合理的
很显然这样是不合理的。
所以论文的做法是在额外拟合一个平面,用平面的法线作为点的移动方向
接着我们应用上边提到的理论。以查询点在平面上的投影点作为坐标系原点,那邻域点在平面上的投影就构成了一个 R 2 \mathbb{R}^2 R2的点集,邻域点 p i p_i pi到平面的距离是 ϕ i \phi_i ϕi,要求解的平面和曲面也可以从上边提过的两个例子中获得启发。这样一说,MLS做滤波的思路是不是就非常直观了呢。
我这里讲的比较简洁,如果想看论文详解,可以移步下面这位博主的内容PCL MLS論文Computing and Rendering Point Set Surfaces研讀筆記
3.3 PCL测试
//核心头文件
#include <pcl/point_types.h>
#include <pcl/search/kdtree.h>
#include <pcl/surface/mls.h>
#include <pcl/io/ply_io.h>
int main(){
// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());
pcl::io::loadPLYFile("D://welding_project//Project1//ply_source//three_edges_new.ply", *cloud);
// 创建搜索树对象
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
// 创建 MLS 对象,并设置参数
pcl::MovingLeastSquares<pcl::PointXYZ, pcl::PointXYZ> mls;
mls.setComputeNormals(true);
mls.setInputCloud(cloud);
mls.setPolynomialOrder(2);
mls.setSearchMethod(tree);
mls.setSearchRadius(5);
// 存储 MLS 平滑后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr mls_points(new pcl::PointCloud<pcl::PointXYZ>);
mls.process(*mls_points);
pcl::io::savePLYFile("D://welding_project//Project1//ply_source//MLS.ply", *mls_points);
}
下面是用实际采集到的数据测试的结果,采集的物体是两个接近垂直的平板,下面展示的是侧视图
其中白色的点云是原始点云,红色的点云是经过MLS滤波之后的点云,可以很明显的看到噪声被减小了。
但是注意两平面交界的地方,数据明显变圆了,说明MLS对于锐利边缘的保持效果较差,因此又有研究者提出了RMLS点云滤波(二)——RMLS(鲁棒移动最小二乘)介绍。
四. 参考文献
[1]Han X F, Jin J S, Wang M J, et al. A review of algorithms for filtering the 3D point cloud[J]. Signal Processing: Image Communication, 2017, 57: 103-112.
[2]Alexa M, Behr J, Cohen-Or D, et al. Point set surfaces[C]//Proceedings Visualization, 2001. VIS’01. IEEE, 2001: 21-29, 537.