(SLAM)對單應矩陣的理解

其實單應矩陣描述的就是同一平面的點在不同圖像之間的映射關系

舉個例子來說明:

假如我們去超市用支付寶付款,而掃描二維碼的時候,我們不需要正對著二維碼,而是多少帶著點角度,你會發現就算偏轉很大的角度也能識別出來。這其中的過程就是先將二維碼從背景中提取出來,并且變成非常工整的矩形二維碼。這個二維碼是一個平面,所以滿足同一個平面的要求。這就是單應矩陣的一個非常重要的應用:圖像矯正。

除此之外單應矩陣還有很多的應用,例如:張正友相機標定法、圖像拼接等。


單應矩陣

兩個相機在拍攝同一個平面的時候,就是如圖所示的效果。

相機成像原理公式:
\left[ \begin{matrix} u\\ v\\ 1 \end{matrix} \right]=\frac{1}{Z} \left[ \begin{matrix} f_x & 0 & c_x\\ 0 & f_y & c_y\\ 0 & 0 & 1 \end{matrix} \right] \left[ \begin{matrix} R & t\\ 0^T &1 \\ \end{matrix} \right] \left[ \begin{matrix} x_w\\ y_w\\ z_w\\ 1 \end{matrix} \right]=\frac{1}{Z}KT \left[ \begin{matrix} x_w\\ y_w\\ z_w\\ 1 \end{matrix} \right]
我們把簡化一下其形式:
\left[ \begin{matrix} u\\ v\\ 1 \end{matrix} \right]= \left[ \begin{matrix} m_{00} & m_{01} & m_{02} & m_{03}\\ m_{10} & m_{11} & m_{12} & m_{13}\\ m_{20} & m_{21} & m_{22} & m_{23}\\ m_{30} & m_{31} & m_{32} & m_{33} \end{matrix} \right] \left[ \begin{matrix} x_w\\ y_w\\ z_w\\ 1 \end{matrix} \right]
M矩陣是一個是一個4*4的矩陣,空間點在同一個平面上z_w=0,則M矩陣就變成了3*3的矩陣。相機不同位置所拍攝圖像,得到的關系式為:
\left[ \begin{matrix} u_1\\ v_1\\ 1 \end{matrix} \right]=M_1 \left[ \begin{matrix} x_w\\ y_w\\ 1 \end{matrix} \right]
\left[ \begin{matrix} u_2\\ v_2\\ 1 \end{matrix} \right]=M_2 \left[ \begin{matrix} x_w\\ y_w\\ 1 \end{matrix} \right]
整理合并就可以得到:
\left[ \begin{matrix} u_2\\ v_2\\ 1 \end{matrix} \right]=M_2M_1^{-1} \left[ \begin{matrix} u_1\\ v_1\\ 1 \end{matrix} \right]
\left[ \begin{matrix} u_2\\ v_2\\ 1 \end{matrix} \right]=H \left[ \begin{matrix} u_1\\ v_1\\ 1 \end{matrix} \right]
其中H就是單應矩陣。

可給出計算單應矩陣的部分代碼,OpenCV中已有現成函數可供調用:

void pose_estimation_2d2d ( std::vector<KeyPoint> keypoints_1,
                            std::vector<KeyPoint> keypoints_2,
                            std::vector< DMatch > matches,
                            Mat& R, Mat& t )
{
    // 相機內參,TUM Freiburg2
    Mat K = ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );

    //-- 把匹配點轉換為vector<Point2f>的形式
    vector<Point2f> points1;
    vector<Point2f> points2;

    for ( int i = 0; i < ( int ) matches.size(); i++ )
    {
        points1.push_back ( keypoints_1[matches[i].queryIdx].pt );//query是要匹配的描述子,train是被匹配的描述子
        points2.push_back ( keypoints_2[matches[i].trainIdx].pt );
    }

    //-- 計算基礎矩陣
    Mat fundamental_matrix;
    fundamental_matrix = findFundamentalMat ( points1, points2, CV_FM_8POINT );
    cout<<"fundamental_matrix is "<<endl<< fundamental_matrix<<endl;

    //-- 計算本質矩陣
    Point2d principal_point ( 325.1, 249.7 );   //相機光心, TUM dataset標定值
    double focal_length = 521;          //相機焦距, TUM dataset標定值
    Mat essential_matrix;
    essential_matrix = findEssentialMat ( points1, points2, focal_length, principal_point );
    cout<<"essential_matrix is "<<endl<< essential_matrix<<endl;

    //-- 計算單應矩陣
    Mat homography_matrix;
    homography_matrix = findHomography ( points1, points2, RANSAC, 3 );
    cout<<"homography_matrix is "<<endl<<homography_matrix<<endl;

    //-- 從本質矩陣中恢復旋轉和平移信息.
    recoverPose ( essential_matrix, points1, points2, R, t, focal_length, principal_point );
    cout<<"R is "<<endl<<R<<endl;
    cout<<"t is "<<endl<<t<<endl;
}

若有錯誤 歡迎指正

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容