其實單應矩陣描述的就是同一平面的點在不同圖像之間的映射關系
舉個例子來說明:
假如我們去超市用支付寶付款,而掃描二維碼的時候,我們不需要正對著二維碼,而是多少帶著點角度,你會發現就算偏轉很大的角度也能識別出來。這其中的過程就是先將二維碼從背景中提取出來,并且變成非常工整的矩形二維碼。這個二維碼是一個平面,所以滿足同一個平面的要求。這就是單應矩陣的一個非常重要的應用:圖像矯正。
除此之外單應矩陣還有很多的應用,例如:張正友相機標定法、圖像拼接等。
單應矩陣
兩個相機在拍攝同一個平面的時候,就是如圖所示的效果。
相機成像原理公式:
我們把簡化一下其形式:
矩陣是一個是一個
的矩陣,空間點在同一個平面上
,則
矩陣就變成了
的矩陣。相機不同位置所拍攝圖像,得到的關系式為:
整理合并就可以得到:
其中就是單應矩陣。
可給出計算單應矩陣的部分代碼,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;
}
若有錯誤 歡迎指正