文章和代碼已更新:
- 最新版本的文章: https://zhuanlan.zhihu.com/p/289620126
- 最新版本的代碼: https://github.com/zhulf0804/PCReg.PyTorch
1. 概要
最近幾年,基于深度學習的點雲配準算法不斷被提出,包括PointNetLK[1],Deep ICP[2],DCP[3],PRNet[4],IDAM[5],RPM-Net[6],3DRegNet[7],DGR[8]等。這些網絡在ModelNet40,Kitti,或3DMatch資料集上進行試驗,其性能與速度均超過了傳統的ICP算法。這些算法或者網絡結構較為複雜,或者結果難以複現,對于把深度學習應用到點雲配準的初學者而言,不是很友好。這裡結合自己的感觸和最近閱讀的PCRNet[9] (兩者不謀而合),介紹一種非常簡單的點雲配準網絡,或許它的結果不如前面提到的DCP, 3DRegNet等效果好,但其簡潔易懂,且效果在ModelNet40上仍優于ICP,速度快于ICP。
本文将要介紹的網絡是基于PointNet + Concat + FC的,它沒有其它複雜的結構,易于複現。因其簡潔性,這裡暫且把其稱作點雲配準的Benchmark。因作者源碼中複雜的(四元數, 旋轉矩陣, 歐拉角之間)的變換操作和備援性,且其PyTorch版本的不完整性(缺少評估模型等,
最近又更新了
),于是根據自己的了解,從頭撸了一遍整個模型: 資料,網絡,評估,訓練,測試,可視化等操作,代碼已開源https://github.com/zhulf0804/PCReg.PyTorch。
章節2介紹模型的Dataloader部分,就是怎麼組織資料的; 章節3介紹模型的網絡部分; 章節4介紹損失函數; 章節5介紹評估名額; 章節6介紹模型的實作及實作過程中遇到的一些坑; 章節7介紹本庫的一些實驗結果; 章節8介紹一些補充資訊,如四元數、旋轉矩陣和歐拉角之間的關系等。
2. 資料
實驗的資料為不帶有normal資訊的ModelNet40,下載下傳位址為modelnet40_ply_hdf5_2048.zip。訓練集中包括9840個樣本,測試集中包括2468個樣本,每個樣本均包括2048個資料點。
-
訓練
對訓練集中的每個樣本template,随機選擇1024個點,并随機産生一個旋轉矩陣R和平移向量t,其中R是繞z軸旋轉 θ 1 ∈ [ − π 4 , π 4 ] \theta_1 \in [-\frac{\pi}{4}, \frac{\pi}{4}] θ1∈[−4π,4π],繞y軸旋轉 θ 2 ∈ [ − π 4 , π 4 ] \theta_2 \in [-\frac{\pi}{4}, \frac{\pi}{4}] θ2∈[−4π,4π],繞z軸旋轉 θ 3 ∈ [ − π 4 , π 4 ] \theta_3 \in [-\frac{\pi}{4}, \frac{\pi}{4}] θ3∈[−4π,4π]随機生成,t是從[-1, 1]均勻采樣生成。把R, t作用于template點雲,生成source點雲,這樣就得到待配準的點雲對。
在訓練時,需要做噪聲資料增強,對source點雲和template點雲中的每個點(x, y, z)加上随機高斯噪聲。
-
測試
對測試集中的每個樣本template,選擇全部的2048個點,同時産生一個旋轉矩陣R和平移向量t(産生方式同訓練),把R, t作用于template點雲,生成source點雲,這樣就得到了待配準的點雲對。
為了公平的對比不同的方法,需要設定随機種子,保證每次測試随機産生的R,t都一樣。
- 相關代碼在
../data/ModelNet40.py
3. 網絡
- Benchmark
Benchmark網絡架構如上圖所示,它的輸入包括source點雲和template點雲,輸出是一個7維向量,表示平移向量 t ∈ R 3 t \in \mathbb R^3 t∈R3和機關四元數 q ∈ R 4 q \in \mathbb R^4 q∈R4(q是機關向量)。
Benchmark把點雲配準當做回歸問題,它包括提取特征層和回歸層。提取特征層是一個PointNet類的網絡,對點雲 P S P_S PS和 P T P_T PT中的每一個點進行1D卷積Conv1d(3, 64, 64, 128, 1024),這樣對每個點生成了1024維的特征,接下來進行MaxPooling操作,source點雲 P S P_S PS和template點雲 P T P_T PT分别得到了1024維的特征 ϕ ( P S ) \phi(P_S) ϕ(PS)和 ϕ ( P T ) \phi(P_T) ϕ(PT)。 P S P_S PS和 P T P_T PT經過的特征提取層是參數共享的。
為了預測source點雲和template點雲之間的變換,需要在兩者之間建立聯系,這裡采用了Concat操作。兩個點雲的特征通過Concat操作變成了2048維的特征。接下來的回歸層就是全連接配接層FC(2048, 1024, 1024, 512, 512, 256, 7)。
網絡的輸出就是平移向量和四元數,四元數進一步可以轉化成旋轉矩陣(變換公式參考章節8中的補充資訊)。
-
Iterative Benchmark
Benchmark網絡結構比較簡單,相信很多人可以設計出這樣的網絡,但經過試驗發現,這樣的網絡效果較差,在ModelNet40上仍舊不能很好的配準。是以在Benchmark的基礎上,提出了下面的Iterative Benchmark。
Iterative Benchmark包括n個Benchmark(PCRNet),要注意的是這n個Benchmark的權重是共享的,是以網絡的容量是沒有增加的,和Benchmark的參數一樣。Iterative Benchmark是如何工作的呢?
在第一次疊代中,source點雲和template點雲被送入到Benchmark(PCRNet),得到初始的變換T(1)。在下一次疊代中,T(1)作用于source點雲得到transformed點雲,和原始的template點雲一塊送入到Benchmark(PCRNet)。經過n次疊代,原始的source點雲和template點雲之間的變換為每一次疊代變換的組合:
T = T ( n ) × T ( n − 1 ) . . . × T ( 1 ) T = T(n) \times T(n-1) ... \times T(1) T=T(n)×T(n−1)...×T(1)
- 相關代碼在
./models/benchmark.py
4. 損失函數
應用于點雲配準中的Loss比較多,關于R, t的MSE Loss,關于歐拉角的Loss,關于點雲的CD(Chamfer Distance) Loss和EMD(Earth Mover) Loss。
本模型中采用的EMD Loss(最先實驗了CD Loss,效果不理想),實作的代碼是借鑒于網上的開源庫https://github.com/meder411/PyTorch-EMDLoss。
-
EMD(Earth Mover Distance) Loss
E M D ( P S est , P T ) = min ψ : P S est − > P T 1 ∣ P S est ∣ Σ x ∈ P S est ∣ ∣ x − ψ ( x ) ∣ ∣ 2 EMD(P_S^{\text{est}}, P_T) = \min_{\psi: P_S^{\text{est}} -> P_T} \frac{1}{|P_S^{\text{est}}|}\Sigma_{x \in P_S^{\text{est}}}||x - \psi(x)||_2 EMD(PSest,PT)=ψ:PSest−>PTmin∣PSest∣1Σx∈PSest∣∣x−ψ(x)∣∣2
-
CD(Chamfer Distance) Loss
C D ( P S est , P T ) = Σ x ∈ P S est min y ∈ P T ∣ ∣ x − y ∣ ∣ 2 + Σ y ∈ P T min x ∈ P S est ∣ ∣ x − y ∣ ∣ 2 CD(P_S^{\text{est}}, P_T) = \Sigma_{x \in P_S^{\text{est}}} \min_{y \in P_T}||x - y||_2 + \Sigma_{y \in P_T } \min_{x \in P_S^{\text{est}}}||x-y||_2 CD(PSest,PT)=Σx∈PSesty∈PTmin∣∣x−y∣∣2+Σy∈PTx∈PSestmin∣∣x−y∣∣2
本庫的loss代碼在
./loss/earth_mover_distance.py
.
5. 評估名額
評估名額主要4個: mse_R, mse_t, mse_degree, time。前面3個和精度有關系,time是和效率有關。
-
mse_R
mse _ R = Σ i = 1 N ∣ ∣ R pred i − R gt i ∣ ∣ 2 \text{mse}\_R = \Sigma_{i=1}^N||R_{\text{pred}}^i - R_{\text{gt}}^i||_2 mse_R=Σi=1N∣∣Rpredi−Rgti∣∣2
N表示待配準點雲對的數量。
-
mse_t
mse _ t = Σ i = 1 N ∣ ∣ t pred i − t gt i ∣ ∣ 2 \text{mse}\_t = \Sigma_{i=1}^N||t_{\text{pred}}^i - t_{\text{gt}}^i||_2 mse_t=Σi=1N∣∣tpredi−tgti∣∣2
-
mse_degree
mse _ degree = Σ i = 1 N ∣ ∣ θ pred i − θ gt i ∣ ∣ 2 \text{mse}\_\text{degree} = \Sigma_{i=1}^N||\theta_{\text{pred}}^i - \theta_{\text{gt}}^i||_2 mse_degree=Σi=1N∣∣θpredi−θgti∣∣2
θ \theta θ表示歐拉角。
-
time
每個點雲對配準的平均時間。
- 相關代碼在
./metrics/metrics.py
6. 實作
網絡結構雖然簡單,但使其能有效work還是很困難的,先說一下在實作過程中走過的坑:
- 網絡結構: 加bn層會使網絡的結果變差。
- 疊代: 基于Benchmark訓練的網絡效果遠不如Iterative Benchmark的結果。
- 損失函數: CD Loss訓練的結果不如EMD Loss。
- 優化器很: EMD Loss在SGD優化器下出現nan,一種有效的政策是采用Adam優化器訓練EMD Loss。
- 初始學習率: 初始學習率設定為1e-2,出現梯度爆炸,最終收斂的值較大; 初始學習率設定為1e-5,收斂時的權重在評估名額上仍然不好。
- 在訓練和預測時,減點雲的均值是不合理的(原作者的代碼是這麼實作的),因為會使得點雲的平移尺度接近于0.
是以,最終在實作時,采用了Iterative Benchmark模型、EMD Loss、Adam優化器。batchsize設定為16,訓練400 epoches,初始學習率設定為1e-4,學習率下降采用MultiStepLR[50, 250]。在訓練和預測時均不減點雲的均值。
另外,要注意的是,一個batchsize中不同的組織資料會帶來網絡訓練的不穩定性,比如相同的代碼,不改任何配置,由于shuffle的存在,訓練結果差别挺大的;是以在訓練時設定了随機種子,保證訓練結果的可複現性。
7. 實驗結果
7.1 實驗結果
實驗比較了Iterative Benchmark和ICP在ModelNet40測試集上的精度和時間,實驗結果如下表:
Method | mse_t | mse_R | mse_degree | time(s) |
---|---|---|---|---|
icp | 0.40 | 0.38 | 11.86 | 0.06 |
Iterative Benchmark | 0.35 | 0.18 | 7.90 | 0.02 |
從表中可以看到,Iterative Benchmark在ModelNet40測試集上的配準結果,從精度(mse_t, mse_R, mse_degree)和速度(time)上是優于ICP的。
7.2 實驗結果可視化
- ICP與Iterative Benchmark的對比
左圖是ICP的配準結果,右圖是Iterative Benchmark的配準結果。圖中的綠色點雲表示source點雲,紅色點雲表示template點雲,另外一個顔色的點雲表示transformed source點雲,即把source點雲與template點雲配準得到R,t,然後R,t作用于source點雲後的結果。括号内表示是平移t的誤差,旋轉矩陣R的MSE誤差和旋轉角度degree的誤差。
從可視化結果可以看到,當待配準點雲的初始位置不好時,Iterative Benchmark的配準結果優于ICP的配準結果。
- Iterative Benchmark的bad cases 上圖是一個bad case,當具有重複性結構時,Iterative Benchmark的結果是不理想的,其結果弱于ICP算法。
7.3 訓練過程可視化
- 測試集的loss和訓練集的loss
- 學習率
- 測試集的mse_R誤差和訓練集的mse_R誤差
- 測試集的mse_t誤差和訓練集的mse_t誤差
- 測試集的角度誤差和訓練集的角度誤差
7.4 思考
Iterative Benchmark在ModelNet40資料集的大部分cases的配準結果比較好的,但以下問題還需要解決:
- 重複性結構或者複雜結構點雲的配準
- 真實資料點雲的配準
- 部分-部分點雲的配準
8. 補充
本章節介紹一些三維旋轉的内容,參考了https://en.wikipedia.org/wiki/Rotation_matrix#Axis_of_a_rotation和https://zhuanlan.zhihu.com/p/45404840。
-
四元數轉旋轉矩陣
設機關四元數 q = w + x i + y j + z k \mathbf{q} = w + x\mathbf i + y \mathbf j + z \mathbf k q=w+xi+yj+zk,其旋轉矩陣為:
R ( q ) = [ 1 − 2 y 2 − 2 z 2 2 x y − 2 z w 2 x z + 2 y w 2 x y + 2 z w 1 − 2 x 2 − 2 z 2 2 y z − 2 x w 2 x z − 2 y w 2 y z + 2 x w 1 − 2 x 2 − 2 y 2 ] R(q) = \left[ \begin{matrix} 1 - 2y^2 - 2z^2 & 2xy - 2zw & 2xz + 2yw \\ 2xy + 2zw & 1 - 2x^2 - 2z^2 & 2yz - 2xw \\ 2xz - 2yw & 2yz + 2xw & 1 - 2x^2 - 2y^2 \end{matrix} \right] R(q)=⎣⎡1−2y2−2z22xy+2zw2xz−2yw2xy−2zw1−2x2−2z22yz+2xw2xz+2yw2yz−2xw1−2x2−2y2⎦⎤
-
旋轉矩陣轉四元數
w = t r ( R ) + 1 2 w = \frac{\sqrt{tr(R) + 1}}{2} w=2tr(R)+1
x = R 32 − R 23 4 w x = \frac{R_{32} - R_{23}}{4w} x=4wR32−R23
y = R 13 − R 31 4 w y = \frac{R_{13} - R_{31}}{4w} y=4wR13−R31
z = R 21 − R 12 4 w z = \frac{R_{21} - R_{12}}{4w} z=4wR21−R12
-
旋轉矩陣轉歐拉角
∣ θ ∣ = arccos ( T r ( R ) − 1 2 ) |\theta| = \arccos(\frac{Tr(R) - 1}{2}) ∣θ∣=arccos(2Tr(R)−1)
T r ( R ) Tr(R) Tr(R)表示矩陣的迹
-
繞x軸旋轉矩陣
R x ( θ ) = [ 1 0 0 0 cos θ − sin θ 0 sin θ cos θ ] R_x(\theta) = \left[ \begin{matrix} 1 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta \\ 0 & \sin\theta & \cos\theta \end{matrix} \right] Rx(θ)=⎣⎡1000cosθsinθ0−sinθcosθ⎦⎤
-
繞y軸旋轉矩陣
R y ( θ ) = [ cos θ 0 sin θ 0 1 0 − sin θ 0 cos θ ] R_y(\theta) = \left[ \begin{matrix} \cos \theta & 0 & \sin \theta \\ 0 & 1 & 0 \\ -\sin \theta & 0 & \cos\theta \end{matrix} \right] Ry(θ)=⎣⎡cosθ0−sinθ010sinθ0cosθ⎦⎤
-
繞z軸旋轉矩陣
R z ( θ ) = [ cos θ − sin θ 0 sin θ cos θ 0 0 0 1 ] R_{z}(\theta) = \left[ \begin{matrix} \cos \theta & -\sin \theta & 0 \\ \sin \theta & \cos \theta & 0 \\ 0 & 0 & 1 \end{matrix} \right] Rz(θ)=⎣⎡cosθsinθ0−sinθcosθ0001⎦⎤
- 相關代碼在
./utils/process.py
參考資料
[1]. PointNetLK: Point Cloud Registration using PointNet [
CVPR 2019
]
[2]. DeepICP: An End-to-End Deep Neural Network for 3D Point Cloud Registration [
ICCV 2019
]
[3]. Deep Closest Point: Learning Representations for Point Cloud Registration [
ICCV 2019
]
[4]. PRNet: Self-Supervised Learning for Partial-to-Partial Registration [
NeurIPS 2019
]
[5]. Iterative Distance-Aware Similarity Matrix Convolution with Mutual-Supervised Point Elimination for Efficient Point Cloud Registration [
ECCV 2020
]
[6]. RPM-Net: Robust Point Matching using Learned Features [
CVPR 2020
]
[7]. 3DRegNet: A Deep Neural Network for 3D Point Registration [
CVPR 2020
]
[8]. Deep Global Registration [
CVPR 2020
]
[9]. PCRNet: Point Cloud Registration Network using PointNet Encoding [
arXiv 2019
]