1. 程式人生 > 其它 >三維點雲處理

三維點雲處理

目錄

三維點雲處理

Cluster

對給定點集\(p_i, i \in {1,2,...n}\)

進行聚類。

K-means

(1) 隨機初始化K箇中心點
(2) 每個點\(p_i\)屬於分配一個距離最近的點
(3) 更新中心點位置
(4) check converge
變種:
K-Medoids(K中心點法):中心點必須從origin點集中選出;能夠有效解決outlier把中心點拉得很遠的情況。
GMM(gaussian mixture model):(2)中hard分配中心點變為soft; (3)每個中心點維護的不僅是座標,而是一個guassian model包含\((\mu, \sum, \pi)\)三個引數,其中\(\pi\)為該中心GM為其它GM混合時的權重。

Spectral Clustering

譜聚類與K-means類方法最大區別在於由基於歐式距離的聚類轉換為“基於連線”的聚類,演算法步驟:
(1) 建立n個點的鄰接矩陣\(M \in R^{n \times n}\)與Degree矩陣D(對角陣,每個元素為M矩陣每行的和)
(2) Laplacian矩陣\(L = D - W\)
(3) 計算L的k個最小特徵值對應的特徵向量\(v_1, ..., v_k\),構成矩陣\(V \in R^{n \times k}\)
(4) 將每V的每行取出得\(y_i \in R^{k}\)進行K-means聚類出\(C_1, C_2,..., C_k\)
(5) 最後根據每個\(y_i\)的聚類結果確定每個\(p_i\)

的聚類結果
pros:
(a) 利用Laplacian矩陣良好特性:特徵值為0的個數即為聯通子圖個數。
(b) eigengap: 根據特徵值的gap能夠自動確定聚類數k。
(c) 基於連線的聚類方式能夠很好解決比如兩個圓環或者兩個月牙巢狀的這種case,相對於基於歐式距離的方法。
cons:
當n較大時,對\(L \in R^{n \times n}\)進行特徵值分解計算量還是挺大的。

Mean-Shift

演算法步驟:
(1) 在點集中任意放下半徑為r的circle
(2) 重複將circle移動到包含點質心位置直到該circle位置不調整
(3) 重複步驟(1)(2),即放下新的circle,如果circle重疊,則保留包含點最多的circle,直到circle數量不再增加
(4) 計算每個\(p_i\)距離哪個circle最近,歸於該cluster。
pros:自動計算聚類中心數量;
cons: 不能處理"兩個巢狀環"

DBSCAN

非常NB與實用的聚類演算法,基於連線。演算法步驟:
(1) 在點集中選擇unvisited \(p_i\)點半徑為r的circle
(2) 如果circle包含點數大於m則點\(p_i\)為core point,否則為noise。將點\(p_i\)置為visited
(3) 對於core point點對應circle裡的點遞迴進行(1)(2)步驟,將所有標記出的core point記為cluster C並移出點集。
(4) 對於剩下unvisited點重複(1)(2)(3)步,直到所有點變為visited。
pros:
自動計算聚類中心;基於連線;對於outliers(noise)魯棒。
cons:
半徑r是人為設定引數,對於密度集中或者分散需要對就設計不同的r。

補充知識:RANSAC: random sample consensus

用來除去outlier,超引數:
\(\tau\):經驗值,點到參考直線距離 \(\tau\)則為內點 => 記錄內點率及內點座標
\(N\):迭代次數,通過期望內點率,以及期望最終confidence兩個先驗值估算出
最終將內點率最高的那次sample出來的直線作為擬合直線,對應的點為內點。

補充知識:Hough直線

用來擬合點集中一條或者多條直線。基本原理:
直線可以用\(y = kx + b\) 來表示,影象空間中一個點在參考數空間k-b中成為一條以k, b為變數的直線,而引數空間中從標為(k, b)的一個點對應為影象空間中的一條直線。給定點集中所有點在引數空間對應了很多線直線,這些直線會近似相交到幾個點簇中,這幾個相交點在影象中空中即為我們要擬合直線。實際操作中k=0這條直線不好表示,所以有時會轉換到引數座標系(\(\theta\), t)或者極座標系(\(\rho\), \(\theta\))中。

點雲特徵點

應用背景:ICP通常需要好的初始狀態下(兩幀點雲的overlap要大)才能迭代出準確的R/T變換。通常使用3D feature matching的方法來獲取良好的初始解。

2D影象haris特徵點

特徵點最直觀:將radius為r的小patch在點p附近shift (u, v),內容變化的劇烈程度。
\(E(u, v) = \sum(I(x+u, y+v) - I(x,y))^2 = [u, v] M [u, v]^T\)
其中,上式通過一階泰勒展開得到的\(M = \begin{bmatrix} I_x^2 & I_xI_y \\ I_xIy & I_y^2\end{bmatrix}\)
如果將M裡面每個\((I_x, I_y)\)都畫出來,可以發現:
如果patch裡是空白,則所有點坍縮在一團;
如果patch裡面是一條線,則散點分佈類似於橢圓;
如果patch裡面是兩條線,則散點分佈類似於兩個相交的橢圓狀。
其實橢圓長軸分佈的範圍就是特徵值\(\lambda\),而方向就是特徵向量所在方向。
早期一系列方法針對M特徵值\(\lambda\)來判斷點p是否是特徵點,稱為Response函式R,常用的是\(R=min(\lambda_1, \lambda_2)\)

3D點雲haris特徵點

當點雲有intensity值時,情況與上述基本相同,不過拓展到3D空間。唯一區別是無法直觀算出\((I_x, I_y)\),因為二維情況可以直接通過上下pixel的梯度,但三維空間領域點不好確定。三維情況主要通過兩步求解:
(1) 我們要求解的就是點p(x, y, z)附近點(x', y', z')雲梯度的變化。
\((x' - x, y - y', z - z') \dot (I_x, I_y, I_z) = I' - I\)
點p半徑為r附近有n個點就有n這個方程,通常是超定方程,可以通過最小二乘來解。
(2) 由於我們知道點p在平面上,則點p的梯度變化也一定在平面上。所以可以將\(I\)通過點p的法向量\(n\)投影到平面上,來去除噪點。

3D點雲ISS特徵點

ISS(intrinsic shape signature):點p與附近r範圍內其它點的協方差距陣\(M \in R^{3 \times N}\),M的三個特徵值分別為\(\lambda_1\), \(\lambda_2\), \(\lambda_3\)。如果點p處於平面,則\(\lambda_1 = \lambda_2 > \lambda_3\);如果點p處於直線,則\(\lambda_1 > \lambda_2 = \lambda_3\);所以如果點p為某個角點,則特徵值各不相等\(\lambda_1 > \lambda_2 > \lambda_3\)。通過該條件篩選出所有特徵點,再通過以\(\lambda_3\)為score進行NMS。

USIP

基於深度學習的無監督方法。出發點在於特徵點不論如何旋轉特徵點應該始終是特徵點。做法是通過將PC隨機旋轉之後過feature point det後出的點經過某個變換之後應該還能完全對齊,基於這個pretext任務構造Loss讓feature point det提出有意義的特徵點。

點雲中的特徵描述子

有了特徵點如何獲取特徵點區域性的描述子呢?也分傳統方法(PFH, FPFH)與深度學習方法。其中傳統方法又分為基於histogram與基於signature兩類方法。

PFH

Point Feature Histogram,傳統方法,基於大小為\(B^3\)的histogram。
(1) 建立LRF(local reference frame):每個pair對可以根據兩點連線\(<p_1, p_2>\)及以兩點法向量\(n_1, n_2\)來建立以\(p_1, p_2\)為中心的兩個座標系,這個兩個座標系的資訊可以用角座標\((\alpha, \phi, \theta)\)來表示。
(2) 點p附近的k個點兩兩之間pair可以形成\(k^2\)個角座標\((\alpha, \phi, \theta)\),通過將這些點散落到每個維度B個grid的3D voxel空間,再把該空間flatten成vector即可得到該特徵點的descriptor \(D \in R^{B^3}\)
評論:很直觀暴力的方法,不過LRF的建立過程很常規還是可以學習一下。

FPFH

Fast Point Feature Histogram,傳統方法,基於大小為\(3B\)的histogram。
(1) SPFH (Simple Point Feature Histogram),同上建立LRF,得到角座標\((\alpha, \phi, \theta)\)每個維度分別進行大小為B的histogram再連線到一起。
(2) 將點p附近的k個點的SPFH根據距離加權平均到一起就到得FPFH。

SHOT

Signature of Histograms of Orientations
將特徵點p附近半徑為r球面空間劃分成32個區域(2x2x8,8根徑線),每個扇區計算出其norm方向\(n_v\),每個特徵點的法線方向計為\(n_u\)
\(cos(\theta) = n_u \dot n_v\)
\(cos(\theta)\)離散化出11個bin,則整個SHOT descritor共表示為 11 x 32 = 352dim的feature。

3D Match

基於DL的方法。
(1) 使用RGBD相機構建3D場景
(2) 針對每個key point提取30x30x30的3D voxel patch。
(3) Positive:不同pose下的同一個keypoint。Negative: 3d空間中不同的patch。
(4) 使用pair wise的constrastive loss對3d siamese network進行訓練。
說明:pair wise的constrastive loss考慮pos < neg小到一個絕對長度\(\gamma\),提升空間是使用相對大小比較的triplet loss。
缺點:3D voxel patch對於旋轉不魯棒。

Perfect Match

3D Match的改進版本,主要引入LRF來解決rotation問題。點p處的LRF建立過程:\(z_p = n_p\)\(n_p\)為法向量;\(x_p\)為所有\(<p, p_i>\)投影到平面形成向量的加權平均。\(y_p = z_p \times x_p\)。loss function使用的是triplet loss。

PPFNet

Point Pair Feature
之所以和之前工作不一樣是直接使用point來提3D feature,而不是先打成3D voxel patch。但是每個點如果直接使用(x, y, z)座標除了位置之外沒有什麼資訊含量的。本文使用每對pair的\(\psi = (\left \| d \right \|, \angle(n_1, n2), \angle(n_1, d), \angle(n_2, d))\)作為一個點,那個pair中有\(k^2\)個pair就有很多點統一送到pointNet中提取feature,與全域性feature進行concat再使用N-tuple Loss進行訓練。

PPF-FoldNet

同上,使用\(\psi\) + point進行特徵提取,只不是Pretext任務不再是對比學習,而是reconstruction,即通過encoder+decoder能否還原出原來的point cloud,使用champer loss來對比兩個點雲是否一致。

總結

點雲配準

Registration:通常建立在已經有比較好的Initialization的情況下,使用Registration進行Refine,常見的Intialization的方式有:
(a) PointCloud的特徵點提取+Matching+RANSAC (類似於2D的image matching)
(b) IMU或者GPS等其它感測器輔助

下面介紹一階Registration方法ICP,與二階方法NDT。

ICP

iterative closest point,總共分四步:
(1) preprocess: random sample, norm space sample
(2) data-association: nearest neighbor (kdtree/octree),normal shooting。總之都是比較粗暴的找到source PC與target PC之間逐點的對應關係,並且把距離過大的pair移除掉。
(3) Cost function:
Point2point
\(E(R, t)=min_{arg_(R,t)}=\frac{1}{N}\sum_{N}^{i}\left \| q_i-R p_i -t \right \|\)
可以證明該式存在近似的閉式解:
\(t = \mu_q - R \mu_p\)
R = UV^T
其中: \(\mu\)為對應PC的質心,而\(U\),\(V\)為去中心化後兩個點雲的內積矩陣的正交矩陣。
Point2Plane
將target point使用surface normal來變成一系列切線集合,再利用source point到平面的關係建立cost function。point2plane不同於point2point,沒有直接的解析解,需要優化求解R/t,我們知道R是有正交矩陣的約束。一種辦法是使用李代數轉換到exp空間進行優化求解。這裡採用第二種方案,即將R使用尤拉角表示為\(R(\alpha)\), \(R(\beta)\), \(R(\gamma)\),再得用每次旋轉量很小的先驗近似\(sin(\theta)=\theta\), \(cos(\theta)=1\),最終解出\(\alpha, \beta, \gamma\)即可,每個點都可以建立一個方程,轉換為\(Ax=b\)的問題,可以使用SVD分解來解出變數。
(4) check converge
如果迭代過程R,t不怎麼變了,就可以停止迭代了。

NDT

normal distribution transform,使用了二階方法(牛頓法)進行更新R/t
(1) 概率化target PC空間
解target PC變成voxel grid,將點數大於m的grid中的點的分佈擬合出一個gaussian distribution,點數小於m的grid進行removal。
(2) Cost Function
問題轉換成為如何將source PC進行R/t變換之後在targe gaussian space中的似然概率最大,將問題轉換成為MLE(maximum likelihood estimation),待估計引數為R/t。
該Cost function使用二階泰勒展開再令關於x的了階導數為0可得到每次優化的步長即為一階梯度\(g\)與二階海森矩陣\(H^{-1}\)的乘積,但二階方法需要解海森矩陣H比較麻煩,實際上可以利用R的\(sin(\theta)=\theta\), \(cos(\theta)=1\)來簡化計算,這裡就不展開說明了。
說明:每次優化一步即可,原因:(a) 二階優化(牛頓法)一步就很快了。(b) 有一些近似再裡面,迭代次數多也不精確。
總結:二階牛頓法其實就是把原本一階的切線替換成了二次函式,直接找二次函式頂點作為下一步的\(x_{i+1}\)
(3) 同ICP進行R/t的update
(4) 同ICP進行check converge
優點:速度快,對initialization稍微不敏感一點。缺點:target space需要概率化,二階法優化複雜。

點雲cls/seg

點雲具有無序性導致使用DL處理比較麻煩,早期存在三類方法:
(a) 將整個空間離散成voxel空間,比如occupy map/TSDF/ESDF等,代表性方法是VoxelNet。缺點:很多空白柵格白學浪費資源。
(b) 使用360度的N個相機陣列將點雲投影到對應多個2D Image,再將2D Image Concat到一起用2D Conv處理。缺點:相機陣列數N很關鍵。
(c) 直接對無序點雲進行訓練,需要克服點雲的無充性,所以訓練的時候就得做一系列各種順序的資料增強,效果還一定好。但是衍生出來PointNet系列還是很經典的。

PointNet

可以做點雲cls/det。本質上 = Shared MLP + MaxPooling。
Shared MLP: n x 3 => n x 1024,即使用MLP對每個點進行升維。
MaxPooling:n x 1024 pool成1 x 1024,從而將n這個維度消除,並且與n的順序無關。這步是解決(c)的關鍵模組。
中間會夾雜各種transform,其實影響不是很大。
PointNet for seg: n x 1024 => n x m,其中m為類別數,從而達到對每個點進行分類的效果。
優點:速度快

PointNet++

相對於PointNet主要兩個改進:
(1) 以set abstraction作為基本單位構成更深Network,set abstraction由以下三個部分構成:
sampling layer: 對點雲進行取樣,使用FPS(Furthest point sample),具體做法是先隨機選一個點,然後選擇離這個點最遠點作為第二點,再選離這兩個點最遠的點作為第三點,以此類推直到選夠N個點。
grouping layer: 以取樣出的點為中心,取出距離每個點一定範圍radius之內的最近K個點為一個group。輸出N x K x (d + C),N為取樣點個數,K為每個group最多點數,d是座標維度,C是每個點屬性特徵。
pointnet layer: 就是上述的PointNet
(2) 上述grouping過程可以使用多種radius,每個radius提取出的K個取樣點範圍不同,從而起來類似於multi-scale的效果。這麼做主要出發點是有些部分點密度高,有些部分密度低,使用相同radius聚合不合理。
(3) Hierachical如下圖所示,主要將不同downsample scale的feature進行融合。
不同group的點雲有密度可能不同,低密度的group需要增大scale,並且有些group需要多個scale融合充分提取特徵。
效果:最終超越PointNet %4以上,當然速度也會相應變慢。

MV3D

早期做基於pointcloud及RGB image做3D object detection的工作。
bird view:pointcloud沿著height拆成若份,每份投影出一個view。
front view:投出depth map
RGB view: 對應的camera的出資料。

三種檢視分別過backbone投出roi pooling之後的feature再進行融合。

總結:早期方法,titan X上0.36s,與實用還有一定差距。

VoxelNet

naive版本就是將pointcloud空間打成NxWxW的空間,使用VFE(voxel feature encoder)/PointNet提出整個voxel空間的feature tensor,最後再將feature tensor使用3D CNN出feature map,最終再類似於FRCNN的RPN一樣出每個anchor的(x, y, z, l, w, h, theta)。
因為實際只有10%的voxel裡面有point,所以將這10%挑選出來單獨過VFE/PointNet得到每個voxel的特徵再用index對應回去,再過後面的3D CNN,可以加快速度。

對比

(1) MV3D, VoxelNet是早期經典方法;
(2) PointPillars = Pillar Feature Net + SSD;即Pillar Feature Net提取3D點雲特徵圖變換成CxHxW的2d image feature map,再使用2d SSD直接出3D boxes;
(3) PointRCNN = PointNet++提3Dfeature + 3D RPN + 3D Roi Pooling + 3D boxes;
(4) Frustum PointNet = 2d detector出2d boxes + 逐box的3d instance seg by PointNet => 3D boxes
(5) PointPainting = 2d seg投影到3d point進行類別染色 + PointRCNN/PointPillars等方法出框
總結:目前貌似還是PointRCNN這類two stage的方法效果更好一些。