其实单应矩阵描述的就是同一平面的点在不同图像之间的映射关系
举个例子来说明:
假如我们去超市用支付宝付款,而扫描二维码的时候,我们不需要正对着二维码,而是多少带着点角度,你会发现就算偏转很大的角度也能识别出来。这其中的过程就是先将二维码从背景中提取出来,并且变成非常工整的矩形二维码。这个二维码是一个平面,所以满足同一个平面的要求。这就是单应矩阵的一个非常重要的应用:图像矫正。
除此之外单应矩阵还有很多的应用,例如:张正友相机标定法、图像拼接等。
两个相机在拍摄同一个平面的时候,就是如图所示的效果。
相机成像原理公式:
我们把简化一下其形式:
矩阵是一个是一个的矩阵,空间点在同一个平面上,则矩阵就变成了的矩阵。相机不同位置所拍摄图像,得到的关系式为:
整理合并就可以得到:
其中就是单应矩阵。
可给出计算单应矩阵的部分代码,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;
}
若有错误 欢迎指正