单张图片计算和下一张图片之间的单应矩阵--无需匹配点
使用场景-平面的映射(如地面,墙面)
单应矩阵的基础知识
链接: Basic concepts of the homography explained with code.
链接: Planar Homographies.
链接: 图像处理之理解Homography matrix(单应性矩阵).
OPENCV官方代码案例: https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/features2D/Homography
代码片
去博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片
.
// An highlighted block
void computeC2MC1(const Mat &R1, const Mat &tvec1, const Mat &R2, const Mat &tvec2,
Mat &R_1to2, Mat &tvec_1to2)
{
//c2Mc1 = c2Mo * oMc1 = c2Mo * c1Mo.inv()
R_1to2 = R2 * R1.t();
tvec_1to2 = R2 * (-R1.t()*tvec1) + tvec2;
}
Mat computeHomography(const Mat &R_1to2, const Mat &tvec_1to2, const double d_inv, const Mat &normal)
{
Mat homography = R_1to2 + d_inv * tvec_1to2*normal.t();
return homography;
}
/*
* pose1 pose2 两个机器的POSE值(世界坐标系)
* extrinc_matrix 相机外参 4*4
* cameraMatrix_K 相机内参 3*3
* 输出:单应矩阵
*/
cv::Mat compute_homography_by_para(cv::Vec3f pose1,cv::Vec3f pose2 )
{
double theta1 = pose1[2] ;
double theta2 = pose2[2];
// 0.389087 Y: A: -0.015 X: 0.05628 Y: -0.000273276 A: -0.007 LS: 0.381486 AS: 0
// X: 0.782331 Y: -0.024205 A: -0.052 LS: 0 AS: 0 0.799277 Y: -0.014131 A: -0.032
cv::Mat M_v_o_1= (Mat_<double>(4,4) << cos(theta1),-sin(theta1),0.0,pose1[0],sin(theta1),cos(theta1), 0.0, pose1[1] , 0.0 , 0.0, 1, 0, 0.0, 0.0,0.0, 1);
cv::Mat M_v_o_2= (Mat_<double>(4,4) << cos(theta2),-sin(theta2),0.0, pose2[0], sin(theta2),cos(theta2), 0.0, pose2[1], 0.0 , 0.0, 1, 0, 0.0, 0.0,0.0, 1);
cv::Mat M_c1_o = extrinc_matrix.inv() * M_v_o_1.inv();//extrinc_matrix * M_v_o_1 ;
cv::Mat M_c2_o = extrinc_matrix.inv() * M_v_o_2.inv();//extrinc_matrix * M_v_o_2 ;
cv::Mat R_1to2, tvec_1to2;
cv::Mat R1 = M_c1_o.rowRange(0,3).colRange(0,3).clone();
cv::Mat tvec1 = M_c1_o.rowRange(0,3).colRange(3,4).clone();
cv::Mat R2 = M_c2_o.rowRange(0,3).colRange(0,3).clone();
cv::Mat tvec2 = M_c2_o.rowRange(0,3).colRange(3,4).clone();
computeC2MC1(R1, tvec1, R2, tvec2, R_1to2, tvec_1to2);
cv::Mat normal = (Mat_<double>(3,1) << 0, 0, 1);
cv::Mat normal1 = R1 * normal;
cv::Mat origin(3, 1, CV_64F, Scalar(0));
cv::Mat origin1 = R1 *origin + tvec1;
double d_inv1 = 1.0 / normal1.dot(origin1);
cv::Mat homography_euclidean = computeHomography(R_1to2, tvec_1to2 , d_inv1, normal1);
cv::Mat homography = cameraMatrix_K * homography_euclidean * cameraMatrix_K.inv();
homography /= homography.at<double>(2,2);
return homography;
}
int main()
{
// 初始化机器移动的两个POSE值
cv::Vec3f pose_vec, next_pose_vec;
pose_vec[0] = 0.389087 ;
pose_vec[1] = -0.024205 ;
pose_vec[2] = 0.05628 ;
next_pose_vec[0] = 0.782331 ;
next_pose_vec[1] = -0.014205 ;
next_pose_vec[2] = -0.052 ;
cv::Mat homography= compute_homography_by_para( pose_vec,next_pose_vec );
Mat mask_output;
warpPerspective(origin, mask_output, homography, Size(origin.cols,origin.rows));
resize(mask_output, mask_output, Size(origin.cols/cutio, origin.rows/cutio));
cv::Mat cmpare(mask_output, cv::Range(330 , image.rows ),cv::Range(0 , image.cols ));// cols
// imwrite(convert.str(),image_next);
cv::namedWindow( "correction", cv::WINDOW_AUTOSIZE );
cv::imshow( "correction", cmpare );
cv::waitKey(0);
return 0;
}