原理,推导过程

代码实现
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <Eigen/dense>
int main()
{
cv::Point2f src_pt[] =
{ cv::Point2f(390,0),cv::Point2f(1250,0),cv::Point2f(1250,840),cv::Point2f(390, 840) };
cv::Point2f dst_pt[] =
{ cv::Point2f(280,220),cv::Point2f(400,220),cv::Point2f(450,430),cv::Point2f(310, 410) };
Eigen::MatrixXd m(8, 8);
for (int i = 0; i < m.rows(); ++i)
{
for (int j = 0; j < m.cols(); ++j)
{
if (i % 2 == 0)
{
if (j <= 2)
{
if (0 == j)
{
m(i, j) = src_pt[i / 2].x;
}
else if (1 == j)
{
m(i, j) = src_pt[i / 2].y;
}
else
{
m(i, j) = 1;
}
}
else if (j >=3 && j <= 5)
{
m(i, j) = 0;
}
else
{
if (6 == j)
{
m(i, j) = -src_pt[i / 2].x * dst_pt[i / 2].x;
}
else
{
m(i, j) = -src_pt[i / 2].y * dst_pt[i / 2].x;
}
}
}
else
{
if (j <= 2)
{
m(i, j) = 0;
}
else if (j >= 3 && j <= 5)
{
if (3 == j)
{
m(i, j) = src_pt[i / 2].x;
}
else if (4 == j)
{
m(i, j) = src_pt[i / 2].y;
}
else
{
m(i, j) = 1;
}
}
else
{
if (6 == j)
{
m(i, j) = -src_pt[i / 2].x * dst_pt[i / 2].y;
}
else
{
m(i, j) = -src_pt[i / 2].y * dst_pt[i / 2].y;
}
}
}
}
}
std::cout << m << std::endl;
Eigen::MatrixXd dst_matrix(8, 1);
for (int i = 0; i < dst_matrix.rows(); ++i)
{
if (i % 2 == 0)
{
dst_matrix(i, 0) = dst_pt[i / 2].x;
}
else
{
dst_matrix(i, 0) = dst_pt[i / 2].y;
}
}
std::cout << "-----------------------------------" << std::endl;
Eigen::MatrixXd perspective_matrix = m.inverse() * dst_matrix;
std::cout << perspective_matrix << "\n-->" << std::endl;
Eigen::MatrixXd ptmatrix_eigen(9, 1);
int i = 0;
for (; i < perspective_matrix.rows(); ++i)
{
ptmatrix_eigen(i, 0) = perspective_matrix(i, 0);
}
ptmatrix_eigen(i) = 1;
std::cout << ptmatrix_eigen << std::endl;
std::cout << "-----------------------------------" << std::endl;
cv::Mat ptmatrix_cv = cv::getPerspectiveTransform(src_pt, dst_pt);
std::cout << ptmatrix_cv << std::endl;
cv::Mat carton = cv::imread("../data/carton2.jpg");
cv::Mat beauty = cv::imread("../data/beauty1.jpg");
cv::Mat tmp;
cv::warpPerspective(beauty, tmp, ptmatrix_cv, cv::Size(carton.cols, carton.rows));
cv::Rect rect(280, 220, 170, 230);
tmp(rect).copyTo(carton(rect));
cv::imshow("perspective_carton", carton);
cv::waitKey(0);
return 0;
}