OpenCV的getPerspectiveTransform()函数 和 warpPerspective()函数配合使用,可以实现图像的拉伸。
下面给一个函数cvMatRect2Tetra(),将矩形图像拉伸成任意四边形。代码:
#include "cvStretch.h"
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_core249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_imgproc249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_highgui249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_ml249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_video249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_features2d249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_calib3d249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_objdetect249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_contrib249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_legacy249d.lib")
#pragma comment(lib, "E:\\cv\\opencv\\build\\x86\\vc11\\lib\\opencv_flann249d.lib")
cv::Mat cvMatRect2Tetra(cv::Mat mtxSrc, int iDstX1, int iDstY1, int iDstX2, int iDstY2,
int iDstX3, int iDstY3, int iDstX4, int iDstY4, int iDstWidth, int iDstHeight)
{
cv::Mat mtxDst;
std::vector<cv::Point2f> src_corners(4);
std::vector<cv::Point2f> dst_corners(4);
src_corners[0]= cv::Point2f(0,0);
src_corners[1]= cv::Point2f(mtxSrc.cols - 1,0);
src_corners[2]= cv::Point2f(0, mtxSrc.rows - 1);
src_corners[3]= cv::Point2f(mtxSrc.cols - 1, mtxSrc.rows - 1);
dst_corners[0] = cv::Point2f(iDstX1, iDstY1);
dst_corners[1] = cv::Point2f(iDstX2, iDstY2);
dst_corners[2] = cv::Point2f(iDstX3, iDstY3);
dst_corners[3] = cv::Point2f(iDstX4, iDstY4);
cv::Mat transMtx = cv::getPerspectiveTransform(src_corners, dst_corners);
cv::warpPerspective(mtxSrc, mtxDst, transMtx, cv::Size(iDstWidth, iDstHeight));
return mtxDst;
}
拉伸之后,目标图仍是矩形,但是源图的左上角将对应目标图的(iDstX1, iDstY1), 右上角将对应目标图的(iDstX2, iDstY2);左下角将对应目标图的(iDstX3, iDstY3);右下角将对应目标图的(iDstX4, iDstY4).
下面的实例调用函数cvMatRect2Tetra:
#include "cvStretch.h"
int main(void)
{
cv::Mat cvSrc = cv::imread("E:\\lenaLeft.jpg");
cv::Mat cvDst = cvMatRect2Tetra(cvSrc, cvSrc.cols /4, 0, cvSrc.cols * 3 / 4, 0,
0, cvSrc.rows -1, cvSrc.cols - 1, cvSrc.rows - 1, cvSrc.cols - 1, cvSrc.rows - 1);
cv::namedWindow("Dst", CV_WINDOW_AUTOSIZE);
cv::imshow("Dst", cvDst);
cv::waitKey();
return 0;
}
源图:
目标图:
对应不到的部分,程序自动用黑色填充。
假如(iDstX, iDstY)的位置超过了目标图的尺寸,则超出部分被截掉。举个例子,把上面代码的目标左上、右上顶点坐标往上推500个像素,跑到目标图之外。
int main(void)
{
cv::Mat cvSrc = cv::imread("E:\\lenaLeft.jpg");
cv::Mat cvDst = cvMatRect2Tetra(cvSrc, cvSrc.cols /4, -500, cvSrc.cols * 3 / 4, -500,
0, cvSrc.rows -1, cvSrc.cols - 1, cvSrc.rows - 1, cvSrc.cols - 1, cvSrc.rows - 1);
cv::namedWindow("Dst", CV_WINDOW_AUTOSIZE);
cv::imshow("Dst", cvDst);
cv::waitKey();
return 0;
}
结果: