(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;
}

若有错误 欢迎指正

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容