深蓝学院的三维点云课程:第一章
一、前言
為什么現在點云應用這么廣泛,就是因為他有深度信息。
像人臉識別用來解鎖手機,比如Iphnoe手機在前邊有一個深度攝像頭,所以它產生的點云真的是一個三維點云;然后很多手機他可能就沒有深度攝像頭,它產生的就是一個圖像,所以有的時候我們就可以使用一張照片就能騙過Arnold手機,但是很難用照片去騙過Iphone手機,因為Iphone他用的是三維信息也就是點云。所以這就是點云為什么會這么廣泛的被應用起來,因為他有深度信息。
PS:激光雷達獲取數據的特點是近密遠疏。
點云形式:
我們有N個點,每個點有XYZ三個坐標,那么很顯然他就是一個的matrix矩陣了,當然我們也可以加一些額外的信息,每個點加一些顏色信息或者有一些法向量之類的。
點云他就是一個矩陣。
點云可以從激光雷達中獲取,RGBD相機中獲取,獲取其他的方式。
三維信息的表達形式:Mesh(三角形):三角形結構太復雜、Voxel Grid():規整的正方體比較的簡單,但是他并不是很高效,因為我們的三維空間大部分都是空的,我們為一個空的空間,放這么多格子是一種對儲存空間的內存浪費、Octree(八叉樹):他解決的效率的問題,因為他只是在有物體的地方才會去細分每一個正方體,所以他的內存占用會少很多,代價就是這個的表達形式比較復雜,不是很好用。
??
from flann import...
Nearest Neighbor Search//用來做點云的最鄰近搜索
點云的難點在:
(1)密度的問題。(尤其在激光雷達里邊近處的物體會反射很多個點,遠處的物體就非常稀疏,導致難以識別。)
(2)不規則。(圖像的每一個像素都是排成一個很規整的網格,所以我要找一個像素的鄰居,只需要上下左右一格就找到了,但是對于點云很難找到離一個點最近的另外一個點;或者一個點一個半徑范圍內的鄰居也是很難的)
(3)沒有紋理信息。(比如在自動駕駛里邊三人并排走在一起就會可能被識別為一個車。)
(4)Un-ordered問題。對于深度學習而言,他輸進去的矩陣是不一樣的,就會產生不一樣的輸出,但我們希望輸出是一樣的,這個就是深度學習的Un-ordered問題。(如何用深度學習去處理這種順序有關系的一些數據)
(5)Rotation旋轉問題。我們去旋轉這些點,我們知道他還是同一個物體,但是他的坐標是完全不一樣的。
偏slam就要算旋轉平移矩陣了。
??
二、PCA & Kernel PCA
2.1、PCA介紹
PCA(Principle Component Analysis):主成分分析。下面是二維和三維下的主成分分析圖:
主成分分析的物理意義:主成分就是我先把這些數據點都投影到一個非常有特征性的方向上,然后每一個數據點在這個方向上的投影就是主成分。在三維情況下這個橢圓的主成分就是他的三個軸。
主成分的應用:
(1)降維(比如說上圖中這些二維的點,如果我只把他投影到x plus上的話,他就變成了一維數據,而且這些一維數據最大程度上保全了這些點的原始信息就是沿著軸的分布,就是降維)
(2)法向量的估計(其實跟PCA是同一個應變量變,用的方法是一樣的,)
(3)PCA可以用來作分類。
2.2、數學基礎
向量的內積就是點乘(就是把其中一個向量投影到另外一個向量上去)。
一個矩陣與一個向量的乘法其實就是對這個矩陣的每一列進行一個線性的組合。
從SVD的角度去理解物理意義:比如說上圖中的矩陣M,他可以被分解成???其中和V都是一個正交矩陣(類似于旋轉矩陣的東西),就是一個對角陣,他的對角線上儲存了M的特征值,如果我把M乘以一個向量,第一步其實就是應用V在高維空間對這個向量做一個旋轉,第一步這個圓被旋轉了一下;第二步就是對這個旋轉后的向量在每一個維度上做一個縮放,所以這個圓就變成了一個橢圓;第三步:再應用,也是高維空間上的旋轉矩陣,所以我就把這個橢圓給旋轉了一下。所以最后M乘以一個向量就是把這個圓變成了橢圓。
旋轉矩陣就是正交矩陣。旋轉矩陣是一個完美的矩陣——正交矩陣。
Q:旋轉矩陣一定是正交矩陣,是對的。反過來正交矩陣一定是旋轉矩陣,對嗎?
A:不對。正交矩陣也可能是反射矩陣,不一定是旋轉矩陣。
單位正交矩陣,且行列式為1,即是旋轉矩陣。一個行列式為1的正交矩陣稱為旋轉矩陣。https://zhuanlan.zhihu.com/p/143056551
正交陣:https://www.cnblogs.com/caster99/p/4703033.html
https://blog.csdn.net/zhang11wu4/article/details/49761121
https://blog.csdn.net/mightbxg/article/details/79363699
Spectral Theorem(譜定理):
有一個對稱矩陣A,他可以被分解為???,(就跟上邊的SVD是一樣的,但是因為A是一個對稱矩陣,所以左右的兩個是同一個,)。就是A的特征值,
如果矩陣的各列向量都是單位向量,并且兩兩正交。那么就說這個矩陣是正交矩陣。(參考xyz三維空間, 各軸上一個長度為1的向量構成的矩陣)
正交矩陣:https://zhuanlan.zhihu.com/p/258464098?utm_source=wechat_session
https://www.doc88.com/p-7844806191895.html
Rayleigh Quotients(瑞利熵):
是一個向量,就是這個向量的模,就是在中間插入了一個對稱矩陣A,之后就可以取得最大最小值。可以從SVD的物理意義去解釋這個事情,如果我把這個A應用到這個向量上邊去,那么其實就是對他做一些旋轉縮放。這個特征值就是對這個向量的縮放,因為旋轉不會改變向量的長度。
所以瑞利熵說的就是我這個A最終能夠拉長或者縮短我這個向量多少倍,就是和是A的最小和最大特征值。
特征值分解只能針對于實對稱矩陣,SVD分解是針對于任何矩陣的。每個實數矩陣都有一個奇異值分解,但不一定都有特征分解。例如,非方陣的矩陣沒有特征分解,這是我們只能使用奇異值分解。特征值分解是一個提取矩陣特征很不錯的方法,但是它只是對方陣而言的,在現實的世界中,我們看到的大部分矩陣都不是方陣,所以要用到奇異值分解。
https://blog.csdn.net/jcjunior/article/details/88064143
https://blog.csdn.net/lyxleft/article/details/84864791
是通過旋轉一下,是通過對做一個高維的旋轉,就是把它乘以一個,所以我們知道旋轉是不會改變一個向量的長度的,所以這個的和和的和是一樣的,
2.3、PCA講解
2.3.1 概念:
PCA輸入:PCA的輸入是就是高維空間的一個向量,我們可以有m個向量,就是一堆高維空間中的點。
PCA輸出:PCA的輸出是一堆主要的向量。比如說就是他最主要的向量,描述了一群點里面最有代表性意義的高維的方向。?
Q:什么叫做最主要的成分?
A:其實就是說如果我把這個些高維點投影到某一個方向上,這些投影后的點方差要最大,就是說這些點在那個方向上,分布的非常的散。
Q:(假設我們已經得到了最主要的向量比如說),我們如何得到??
A:就是我們先把這一組輸入里邊的屬于的成分都去掉,然后我們再找剩下的東西里邊的最主要的成分,就得到第二個。
Q:第三個最主要的成分怎么得到?
A:就是我把第二個最主要的方向的成分都去掉,同上就可以了。
??
2.3.2 PCA證明
- (1)首選i我們先把這一堆點,做個Normalize,把他的平均值設成0,也就是減去平均值,因為我們關心的是方向,所以他中心點在哪里對我們并沒有太大關系,把它設為0。
- (2)然后PCA最主要的方向定義就是說這些點投影到一個方向上面,他的方差最大,所以那我就先投影,投影就是兩個向量的內積,所以我們把每一個數據點把它投影到上邊去,就得到一個,就是我這個點投影到方向上有多長,就是。
- (3)然后說PCA要算方差,那我就算方差,因為我們在(1)中已經減掉了一個mean,那方差就是的平方的和,最后再寫成矩陣的形式。PCA要干的事情就是找到方差在某一個方向上的最大值,也就是它的最大值。這個與之前的瑞利熵很相似。
- (4)最后我們直接用瑞利熵的定義就可以得到方向到底是個什么樣的東西。
- (5)所以用一下瑞利熵和譜定理,把這個H分解成???,然后最主要的向量這里就是,然后就是的第一列。
- (6)因為我們可以用SVD的形式再去分解一下這個H。為什么我們要寫成SVD的形式,因為下面我們就可以使用SVD的形式去求第二個最主要的方向。我們已經得到了最主要的方向,求的時很簡單,把這些數據點里面屬于的成分給去掉,什么叫做的成分呢?就是我把每一個數據點投影到這個方向去,然后再把數據點減掉這個的成分就好了,然后把它再寫成矩陣的形式。
- 然后重新用SVD和的形式來看一下,,因為其實是一個旋轉矩陣就是正交矩陣,他的每一列都是互相垂直的,所以中間的除了i等于1的情況下都等于0。
總結:如果我們有一堆輸入的點,每一個點都在n維空間,做PCA就是:
- 第一步:就是減掉這些數據點的中心。
- 第二步就是做H這個矩陣的SVD找到他的,那么他的第一個主向量就是的第一列,第二個主向量就是的第二列,以此類推。
- PCA可以把他理解為基地的置換過程,就是我有一堆高維的數據點,然后如何去找出一組基底,使得第一個基底就是最有代表性的方向,也就是說他在這個基底的方向上分布的最廣;然后第二個基底當然就是垂直與第一個基底的另外一個方向了,以此類推。所以PCA可以理解為一個基底的置換過程。?
2.3.3PCA的應用
第一個應用在降維上:
我們有一堆n維(n可能很大)數據點,使用一種辦法把這個高維(就是n維)數據點投影到一維空間里邊去,而且盡可能的保留他的特征;
辦法就是:我們先用PCA找到他的個主向量,那么我就得到了個,這時候我們就把分別投影到每一個上邊去,就可以得到了每一個在每一個方向上的投影,所以我們最后得到的每一個就是每一個向量在每一個方向上投影的成分,所以一個n維的點其實可以用一個維的這個系數來代替。再如何從維重新回到n維呢?就做一個和就行了,其實這個a就是每一個x在z上邊的投影,那么我就把這個投影重新加起來就行了,當然我們經過了降維再升維肯定會有數據上的損失,除非我之前的l等于n,那么他就是一個完整的基地置換過程,不會是損失任何的信息,只要l是小于n的就會產生數據的損害,但是因為我們的這些主向量都是經過精心挑選的,所以他的數據的損失會比較小。
PS:Google了解一下Eigenfaces。
PCA的python實現:
##Python實現PCA
import numpy as np
def pca(X,k):#k is the components you want#mean of each featuren_samples, n_features = X.shapemean=np.array([np.mean(X[:,i]) for i in range(n_features)])#normalizationnorm_X=X-mean#scatter matrixscatter_matrix=np.dot(np.transpose(norm_X),norm_X)#Calculate the eigenvectors and eigenvalueseig_val, eig_vec = np.linalg.eig(scatter_matrix)eig_pairs = [(np.abs(eig_val[i]), eig_vec[:,i]) for i in range(n_features)]# sort eig_vec based on eig_val from highest to lowesteig_pairs.sort(reverse=True)# select the top k eig_vecfeature=np.array([ele[1] for ele in eig_pairs[:k]])#get new datadata=np.dot(norm_X,np.transpose(feature))return dataX = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])print(pca(X,1))
結果:
? ?
搞了半天結果不是很一樣啊!分析一下吧!
sklearn中的PCA是通過svd_flip函數實現的,sklearn對奇異值分解結果進行了一個處理,因為ui*σi*vi=(-ui)*σi*(-vi),也就是u和v同時取反得到的結果是一樣的,而這會導致通過PCA降維得到不一樣的結果(雖然都是正確的)。
用sklearn的PCA與我們的PCA做個比較:(結果見上圖右)
##用sklearn的PCA
from sklearn.decomposition import PCA
import numpy as np
X = np.array([[-1, 1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
pca=PCA(n_components=1)pca.fit(X)
print(pca.transform(X))
參考鏈接:https://blog.csdn.net/program_developer/article/details/80632779?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159046726919725256729568%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=159046726919725256729568&biz_id=0
https://blog.csdn.net/qq_45269116/article/details/106353433
2.4、Kernel PCA講解
上述普通的PCA其實是一個線性的PCA,因為所謂的矩陣乘法也是一個線性操作而已,因為矩陣乘以向量其實是對矩陣列的線性組合,所以我們遇到的數據如果不是線性的。
定義一個函數φ,把二維的給提升為3維的,第三個維度選擇兩個坐標的平方和(其實就是極坐標的意思,因為他就是原來的點距離坐標原點的距離),變成三維空間之后呢我們就可以找到一個線或者平面把數據區分開,即這個時候只需要做一個普通的線性PCA就能夠實現把紅色綠色給分離開,只是這個時候是在三維空間不是在原來的二維空間。
升維操作:將原來二維空間的數據,升到三維空間,再做以劃分。這個升維操作就叫做Kernel PCA。
步驟:
- 把原來維度的數據,通過函數給提升為。
- 然后得到之后,后邊的操作和線性PCA是一模一樣的(唯一的區別就是我們現在是在上工作)。
- (1)之后先把他變成平均值為0。
- (2)算一下矩陣。
- (3)要解他的特征值和特征向量。
難點:1、怎么選取這個升維函數;2、有時間升維之后的數據會非常的高,比如說我們的一個圖片可能就是一個30x30的那么他就是一個900維或者更高維度的向量,那么這個時候在高維空間里邊做矩陣的運算是非常耗費運算能力的,所以需要避免這種高維的操作,節省一下運算資源。這就是為什么提出了核PCA,我們就可以避免這種高維的操作,也可以更容易的選擇這個升維函數。
第一步:給出一個結論就是這個特征向量可以表達成數據點的線性組合。是系數,就是映射到高維中的數據點。scalar表示標量,一個數字。
就是原來我們是在解這個特征向量的,但是現在我們可以把他看成是找一些系數,只要我們找到了這些系數,實際上我們就找到了這些特征向量。
核函數其實就是高維空間的一個內積,。這里還有兩個和未被解決掉,因為我們不知道這個核函數長什么樣子,所以暫時還不能用它。
KPCA舉例:
選擇二次多項式作為核函數,我們就可以得到不同的主成分,橫軸是First component就是我們算出來的第一個主向量,我們把原來的數據投影到第一個主向量上面,得到一個數字,這個數字就是數據點在新的方向上的數值;Y軸是Second component就是第二個主成分,我把我的數據點投影到第二個主向量上邊去就可以得到一個數值,我們可以看到只需要投影到第一個主成分上邊去綠色藍色和紅色就已經很明顯被分開了。
也可以是通過使用其他核函數,比如說這里使用高斯核函數,同樣的X軸就是的第一個主成分,就已經非常好的把3種顏色給區分開了,
?
?
?
?
總結
以上是生活随笔為你收集整理的深蓝学院的三维点云课程:第一章的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++:将char*指针强制转换成一个指
- 下一篇: Pycharm报错合集:在pycharm