相機位姿求解 3種方法
目前在做通過雙目攝像頭獲得R t的部分,通過閱讀《Multiple View Geometry in Computer Vision II》瞭解到有三種形式:
1. 2D-2D: 特徵點在同一平面或近平面時,通過Homograpy Matrix可以恢復相機位姿;當特徵點的深度明顯不同時則需要利用對極幾何,通過求得Fundamental Matrix或者Essential Matrix來恢復相機位姿。
2.2D-3D: 通過已知的三維點,以及這些點與給定特徵點的關係,恢復相機位姿,常見的是PnP。
3.3D-3D: 使用ICP對前後兩幀各自的三維點進行匹配,得到兩幀間的相對位姿。
1. 特徵點法
特徵匹配之後,你得到了一組配對點,以及它們的畫素座標。剩下的問題是說,怎麼用這組配對點去計算相機的運動。這裡,根據感測器形式的不同,分成三種情況:
- 你用的是單目相機,於是只有2D-2D的配對點;
- 你用的是RGBD或雙目相機,於是你有3D-3D的配對點;
- 你只知道一張圖中3D資訊,另一張圖只有2D資訊,於是有3D-2D的配對點。
第三種情況可能出現在單目SLAM中,你通過之前的資訊計算了3D的地圖點,現在又來了一張2D影象,所以會有3D-2D的情況。或者,在RGBD和雙目中,你也可以忽略其中一張圖的3D資訊,使用3D-2D的配對點。 無論如何,這三種情況都是現實存在的,所以處理方式也分為三種。
為保持行文清楚,先來把變數設一下。假設某個左邊的特徵點叫,右邊配對的點叫,它們都以畫素座標給出。同時,以左邊圖為參考系,設右邊圖相對它的運動由旋轉和平移描述,相機內參為。由於這兩個點肯定是同一個空間點P的投影,那麼顯然:
(1) 這裡是兩個點的距離,要取齊次座標,取非齊次座標。又說,既然左邊都取齊次了,乾脆齊次到底吧,於是去掉那倆深度:
(2)
該等式在齊次意義下成立,也就是說乘以任意非零常數仍然是等的。不懂的同學請去學習小孔成像原理。我們覺得右邊的內參挺煩人的,於是記
(3)
這倆貨叫歸一化相機座標,也就是去掉內參之後的東西,剩下的就簡單了:
(4)
就這樣。所以相機位姿估計問題變為:你有很多個
------------------------------------------------
1.1 2D-2D,分解E和F的情況:
在2D-2D情況下,你只有兩個點的2D座標,這種情況出現在單目SLAM的初始化過程中。這時我們只有一個 (4) 式,還是乘任意常數都成立的操蛋情形。沒辦法,兩邊叉乘吧:
(5)
這東西右邊的兩個,自己叉自己就沒了。然後,再同時兩邊左乘一個:
(6)
發現左邊的乘了一個和自己垂直的東西,當然是零了,於是就只剩下:
(7)
一個東西等於零,看起來很帥哦。這個牛逼的玩意叫做對極約束(Epipolar Constraint)。簡而言之,隨便你出一組匹配點,都會有這麼個約束成立。
對極約束這東西在幾何上的意思就是這貨的混合零(從影象角度來看),所以它們是共面的向量。既然兩個匹配點是同一個點的投影,那不共面還能上天麼?當然是共面的了。於是,為了好看,又把中間那倆定義成一個:
(8)
這個E叫做Essential(本質)矩陣(別問我為什麼叫Essential,就是這麼叫的)。所以(7)變為:
(9)
這個約束只有E,但我們的目標是求呀,於是求解變成了兩步:
- 用一坨配對點算E;
- 用E算R,t
不妨再說說這兩步怎麼算。
從配對點算E:
最簡單的方式是把E看成單純的一個數值矩陣,忽略它裡面各元素的內在聯絡。當然這麼做的時候你實際要清楚E是有內在性質的,我就直接告訴你這貨的奇異值是一個零加倆一樣的數就完了,證明不寫了。E由t和R的叉積組成,t是仨自由度,R是仨自由度,一共六個。又由於等式為零這樣的約束,乘任意非零常數都成立,也就是對E隨便乘個數,對極約束還是成立的,所以自由度減一,一共五個。因為E有五個自由度,所以最少拿五對匹配點可以把它算出來,這個乃是“五點法”(這幫搞CV的人腦子真樸實都不取個帥點的名字……)。
又,五點法用了E的奇異值這種奇怪的性質,對E引入了非線性約束,解起來麻煩。所以另一個法子是把E看作數值矩陣,然後解它每一個元素就行了唄。E一個九個數,去掉一個非零常數的因子,還剩八個自由度,所以最少拿八對匹配點就可以算出E,粗暴地把E拉成長條即可。比方說對極約束展開後是這樣的:
(10)
把E拉成一個向量扔到右邊:
(11)
這裡:
(12)
簡單吧,現在你搞出了一個線性方程。當你有八對點時,就變成了方程組,磊起來是這樣的:
(13)
然後就是愛怎麼解就怎麼解了。可逆時求逆,不可逆時求偽逆和最小二乘解,矩陣論裡都有,不說了。這個方法最少用八對點,所以叫什麼?對,八點法(你倒是取個好聽點的名字啊喂)。
然後就是用E算R,t的問題了。
這個推導也沒啥好說的,直接給答案吧,推起來太麻煩。先把E給奇異值分解了:
(14)
完了之後這麼一算就得到了R,t:
(15)
這裡對任意一個t加個相反號,對極約束仍然滿足,所以你會得到四個解。這四個解畫出來是這樣的:
怎麼看這個圖呢?兩個小紅點是我們找的配對點,它們都是P的投影。你會看到這四個解裡小紅點的位置都是不變的。那麼哪種情況是真實的呢?廢話,當然是第一種。因為只有第一種情況裡,P出現在相機的前面。什麼?你的相機還能看到身後的東西?你確實不是在逗我?
於是,在驗證之後,就能確定唯一的解了。另外再囉嗦一句,當你不知道內參時,只有畫素座標,那麼對極約束為:
(16)
這時中間那貨叫做F(Fundamental,基本矩陣),和E大同小異但是性質比E麻煩點。因為SLAM裡通常認為相機已經標定好了所以也用不著它了。
------------------------------------------------
1.2 2D-2D,分解H的情況 另一種情況是你找的那些點都位於一個平面上,比如說你的相機是朝天花板或地板看的,這時候分解E和F會出現退化,要用另一種方式來解。
這圖來自wikipedia.
你們不是在平面上嗎?來啊,我們就把平面搞出來。平面方程為:
(17)
然後對兩個點,有:
(18)
這個式子的好處是直接推出了兩個座標之間的關係。把中間那坨東西記為(Homography,單應矩陣),於是:
(19)
這貨也沒啥大不了的。和之前一樣,問題變為:
- 怎麼用給定的一堆匹配點算H;
- 怎麼用H算出R,t,n,d
講起來又是一堆麻煩事。總之第一步比較容易,把H拉成一長條扔到一邊求個線性方程組就行了;第二步比較麻煩,要用到SVD和QR分解。最後你會得到八組解,然後有一串步驟告訴你如何從這八組解裡選出最好的。步驟實在是比較長我就懶得寫了。總之你要知道,在特徵點位於平面上時,分解H;否則分解E或F。
------------------------------------------------
1.2 2D-2D,討論
稍微說幾句。2D-2D的情況出現在單目SLAM的初始化中,你沒有別的資訊,只能這樣子做。其中,分解E或F的過程中存在幾個問題。E這個東西具有尺度等價性,隨便乘個數仍是同一個。所以拿它分解得到的R,t也有一個尺度等價性,特別是t上有一個因子,而自身具有約束,沒有關係。換言之,在分解過程中,對乘以任意非零常數,分解都是成立的,這個叫做單目SLAM的尺度不確定性。因此,我們通常把t進行歸一化,讓它的長度等於1。或者讓場景中特徵點的平均深度等於1,總之是有個比♂例的。
此外,分解E的過程中,如果相機發生的是純旋轉,導致t為零,那麼,得到的E也將為零。零分個毛線!於是,另一個結論是,單目初始化不能只有純旋轉,必須要有一定程度的平移!必須要有一定程度的平移!必須要有一定程度的平移!
1.3 3D-3D,ICP:
下面來討論簡單點的情況:你不光得到了匹配點,還知道這兩組匹配點的深度,於是有了3D-3D的匹配。因為你知道匹配,這種情況下 R,t 的估計是有解析解(閉式解)的。否則,如果只有兩堆點而不知道匹配,則要用迭代最近點(Iterative Closest Point, ICP)求解。閉式解可以稍加推導,不喜歡看推導的同學可以跳過。
假定你找的兩組點是這樣的:
配對好之後,每個點滿足關係:
一開始不知道R,t,所以算一個誤差再求它最小化。誤差為:
最小化它:
簡單吧。這裡可以用一個技巧,先把兩組點的質心設出來,記住不帶下標的是質心:
然後處理一下目標函式:
這裡的技巧無非是先加一項再減一項而已。注意到交叉項部分中,在求和之後是為零的,因此優化目標函式可以簡化為:
嘛,這兩項裡,左邊只和旋轉矩陣R相關,而右邊既有R也有t,但只和質心相關。因此,只要我們獲得了R,令第二項為零就能得到t。於是,ICP可以分為以下幾個步驟求解:
- 計算兩組點的質心;
- 計算去質心座標:
- 求解旋轉R;
- 根據旋轉和質心解t:
t很簡單,問題是R怎麼解?這東西的平方誤差展開為:
注意到第一項和R無關,第二項由於,亦與R無關。因此,實際上優化目標函式變為:
這個優化問題的解法見文獻[1],這裡只給結果。首先定義:
對W進行SVD分解,然後令:
於是就得到了旋轉。 總之就是有閉式解,很簡單,因為有匹配。在不知道匹配的時候,情況比較麻煩,通常你要假設最近點是配對點,所以叫迭代最近點。但是既然我在講特徵點法,匹配就是知道的,什麼迭代最近見鬼去吧。
------------------------------------------------
1.4 3D-2D,PnP
PnP(Perspective n Points)就是你有n個點的3D位置和它們的投影,然後要算相機的位姿。這個倒是SLAM裡最常見的情況,因為你會有一堆的地圖點和畫素點等著你算。PnP的做法有好多種:直接線性變換,P3P,EPnP,UPnP等等,基本你去找OpenCV的SolvePnP中的引數即可,好用的都在那裡。除此之外,通常認為線性方程解PnP,在有噪聲的情況下表現不佳,所以一般以EPnP之類的解為初始值,構建一個Bundle Adjustment(BA)去做優化。上面那堆演算法題主自己查文獻比較好,有大量的實現細節。當然你也可以完全不鳥他們,直接調cv的函式,反正人家早實現好了……
扯到BA不妨多說幾句,BA其實蠻容易理解的,只是名字聽上去不那麼直觀。首先,你有3D點:
然後你又知道了投影:
於是算一個誤差:
然後讓它們最小化:
就行了。這就叫最小化重投影誤差,也叫BA。當然實際算的時候,由於R,t自身帶有約束,所以要轉到李代數上算,這裡不展開。
直觀的解釋如上圖。我們通過特徵匹配,知道了和是同一個空間點P的投影,但是不知道相機的位姿。在初始值中,P的投影與實際的之間有一定的距離。於是我們調整相機的位姿,使得這個距離變小。不過,由於這個調整需要考慮很多個點,所以最後每個點的誤差通常都不會精確為零。總之,我們就寄希望於這個誤差會越調越小了。為什麼越調越小呢?因為我們往往會沿著負梯度方向去調唄。當然解釋起來又得涉及一些非線性優化的東西,什麼高斯牛頓之類的,請查非線性優化教材。
BA是萬金油,你看哪個問題不爽就把它扔到優化目標裡,然後讓計算機幫你優化就行。當然這東西非凸的時候要當心初值,否則一不小心就掉在區域性坑裡爬不出來……
好了,特徵點法就說到這裡。直接法的話……有點更不動,可以參考我講直接法的部落格:直接法 - 半閒居士 - 部落格園
就這樣,躹躬。
[1] Arun, K Somani and Huang, Thomas S and Blostein, Steven D, Least-squares fitting of two 3-D point sets, PAMI, 1987.