相機姿態反求
透過相機拍攝的影象,來反推相機拍攝時的位置和旋轉,是圖形學中一個比較有價值的問題。本文透過一步步簡化問題的思路,最終使用一個簡單的數學模型,對相機的姿態進行求解。
相機姿態反求,通常是根據數個已知點的座標資訊及其在影象上的位置,透過計算來獲取相機的座標位置和旋轉角。
可以先考慮一個更簡單的問題,如果已知點的世界座標和在相機空間的座標,能否求解相機的姿態資料?
相機的空間轉換矩陣可以透過相機的三個軸 AxisX、AxisY、AxisZ 和位置 Pos 得到,有了已知點的世界座標 PosW 和相機空間座標 PosC ,我們可以得到下面的關係:
對於 X、Y、Z 三個分量,都可以得到一個方程(以 X 分量為例):
相機的資料都是未知量,所以上式是四元一次方程,只要有四個已知點的資料,就可以求解方程了。所以對於相機反求問題來說,至少需要四個已知點。
由於世界座標一般都是連續的,而相機的畫面是由畫素組成,所以是離散的。這必定會導致細節資訊的丟失,所求的相機姿態也不是精確值,但畫面畫素越高的話,求解的姿態精度也越高。此外,如果已知點的數量大於四個,可以四個一組分成多個組,分別求解姿態資料,然後把多個組的結果綜合起來減小誤差。
現在問題變為,如何得到已知點在相機空間的座標?
目前有已知點的世界座標 PosW ,和已知點在相機畫面上的位置(即螢幕座標 PosS )。但螢幕座標資料 PosS 是二維的,沒有深度資訊,無法獲得相機空間的座標。
根據相機的不同型別(計算機渲染用的虛擬相機,或真實的物理相機,包括廣角、超廣角、魚眼鏡頭等),其實都有一套光線計算方法,即從相機中心朝向畫素的單位向量。
所以透過 PosS ,可以計算出相機朝向已知點的單位向量 Ray ,如果能得到已知點到相機中心的距離 Dist ,我們便可以計算出已知點的相機空間座標 PosC=Ray * Dist 。
現在問題又簡化為,如何得到已知點到相機中心的距離?
僅透過螢幕座標 PosS 和單位向量 Ray 是無法求解的。但別忘了,之前說過,反求相機需要至少四個已知點,所以我們可以透過已知點之間的關係,來構造方程求解。
已知點示意圖
假設有四個已知點(不一定共面),根據它們在畫面上的位置可以得到四個向量 r1、r2、r3、r4 ,設已知點到相機中心的距離分別為 x、y、z、w ,則四個已知點的相機空間座標可以用 r1*x、r2*y、r3*z、r4*w 表示。
因為有四個已知點的世界座標,所以可以計算出兩兩之間的距離,我們把四個已知點的六個相互距離用 G~L 表示,可以得到下列方程組:
先嚐試展開方程,以第一個方程舉例:
由於距離 G~L 始終為正,且開方運算在 Y 軸右側是單調的,所以等式兩邊平方無影響。為了方程的簡潔,在此也更新 G~L 的定義,從距離改為距離的平方。 繼續展開:
因為 r1~r4 都是單位向量,模長為1,所以方程可以化簡為:
可以看到,方程最後與單位向量的具體值無關,只與向量間的點積值有關。我們可以把四個向量的六個點積值分別用 A~F 表示,則方程組如下:
離結果越來越近了呢。
最終,問題簡化為求解四元二次六個方程的解。
正如前面所說,相機畫面中的畫素是離散的,所以向量的方向會有一定偏差,從而點積值也會有誤差,上述方程並不能得到距離的精確解,但可以獲得足夠逼近的值。
六個方程不太好解,我們可以把它們合為一個。方程可以先化為等於0的等式:
六個等式都是0,那麼和肯定也為0:
考慮到正負相抵為0的情況,要保證原先六個等式的絕對值為0,可以採用平方和:
這樣我們就得到了一個誤差函式,當該函式值最小時,即為 x、y、z、w 最接近真實距離的數值解。不過通常來說,很難求得全域性最小值,我們可以從極小值入手。
普遍的做法是採用梯度下降法,隨機取四個值作為 x、y、z、w 的初始值,然後按照上式計算誤差函式的結果。如果結果足夠小(或減小的值足夠小),則停止運算;如果結果還很大,則每個變數朝自己的偏導方向移動一點,進行下一輪迭代。
其中 η 為學習率,而對於我們的誤差函式來說,x、y、z、w 的偏導分別是:
綜上,要透過影象確定相機的空間位置和旋轉,可以先在影象上找到四個能夠確認世界座標的已知點,然後計算得到四個向量的點積值和四個座標的距離平方值,共十二個引數,使用梯度下降法對誤差函式進行迭代運算,獲得已知點到相機中心的距離,最後透過相機矩陣解四元一次方程得到相機的姿態資料。