線性三角化法 Triangulate


定義:slam中的三角測量指通過不同位置觀測一個三維空間中特征點的夾角,從而測得點的深度值;同理亦可通過三角化恢復二維特征點的三維坐標,單目情況下由於平移t尺度的不確定性只能恢復相對三維坐標。

考慮圖像 I1 I2,以左圖為參考,右圖的變換矩陣為 T。相機光心O1 O2。在 I1 中有特征點 p1,對應 I2 中有特征點 p2理論上直線 O1p1 O2p2 場景中會相交於一點 P,該點即是兩個特征點所對應的地圖點在三維場景中的位置。

然而由於噪聲的影響,這兩條直線往往無法相交 因此,也可以通過最二小乘去求解。

 


方法:

目標:在此使用DLT恢復$p_1$  ,$p_2$  對應的三維坐標 X;

已知:相機內參K ,外參$T_1$,$T_2$  三維點P對應的圖像點$p_1$  ,$p_2$像素坐標$x_1=\begin{pmatrix}u_1\\v_1\\1\end{pmatrix}$  ,$x_2=\begin{pmatrix}u_2\\v_2\\1\end{pmatrix}$;

 

相機矩陣 $P=KT$        其中  $K 3 \times3$  ,    $T=[R|t]  3\times4$  ;

像素坐標 $x_1=KT_1X=P_1X$;

    $x_2=KT_2X=P_2X$;

通過叉乘消去純量因子,使每個圖像點得到三個方程,其中兩個是線性獨立的,對於第一幅圖像有;

$x_1^{\wedge}x_1=x_1^{\wedge}PX=0$

其中 $x_1^{\wedge}=\begin{pmatrix}0&-1&v_1\\1&0&-u_1\\-v_1&u_1&0\end{pmatrix}$

展開得

$u_1\left(P^3_1X\right)-\left(P^1_1X\right)=0$

$v_1\left(P^3_1X\right)-\left(P^2_1X\right)=0$

$u_1\left(P^2_1X\right)-v_1\left(P^1_1X\right)=0$

其中$P^1$ 是P的行,這些關於X的分量是線性的;

 

同理對於第二幅圖像也可以得到三個方程;

 

各取兩個方程得到四個齊次未知量為四的方程,組成$AX=0$的方程;

$A=\left(\begin{array}{cc}{u_{1} P_{1}^{3}} & {-P_{1}^{1}} \\ {v_{1} P_{1}^{3}} & {-P_{1}^{2}} \\ {u_{2} P_{2}^{3}} & {-P_{2}^{1}} \\ {v_{2} P_{2}^{3}} & {-P_{2}^{2}}\end{array}\right)$

通過SVD解 $AX=0$  得到X

 


代碼

 1 **
 2  * @brief 給定投影矩陣P1,P2和圖像上的點kp1,kp2,從而恢復3D坐標
 3  *
 4  * @param kp1 特征點, in reference frame
 5  * @param kp2 特征點, in current frame
 6  * @param P1  投影矩陣P1
 7  * @param P2  投影矩陣P2
 8  * @param x3D 三維點
 9  * @see       Multiple View Geometry in Computer Vision - 12.2 Linear triangulation methods p312      chinese 218
10  */
11 void Initializer::Triangulate(const cv::KeyPoint &kp1, const cv::KeyPoint &kp2, const cv::Mat &P1, const cv::Mat &P2, cv::Mat &x3D)
12 {
13     // 在DecomposeE函數和ReconstructH函數中對t有歸一化
14     // 這里三角化過程中恢復的3D點深度取決於 t 的尺度,
15     // 但是這里恢復的3D點並沒有決定單目整個SLAM過程的尺度
16     // 因為CreateInitialMapMonocular函數對3D點深度會縮放,然后反過來對 t 有改變
17 
18     cv::Mat A(4,4,CV_32F);
19 
20     A.row(0) = kp1.pt.x*P1.row(2)-P1.row(0);
21     A.row(1) = kp1.pt.y*P1.row(2)-P1.row(1);
22     A.row(2) = kp2.pt.x*P2.row(2)-P2.row(0);
23     A.row(3) = kp2.pt.y*P2.row(2)-P2.row(1);
24 
25     //Ax=0
26     cv::Mat u,w,vt;
27     cv::SVD::compute(A,w,u,vt,cv::SVD::MODIFY_A| cv::SVD::FULL_UV);
28     x3D = vt.row(3).t();//豎排
29     x3D = x3D.rowRange(0,3)/x3D.at<float>(3);//齊次  尺度變換成1
30 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM