opencv学习笔记三十四:透视变换

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为:

u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中
变换矩阵可以拆成4部分,表示线性变换,比如scaling,shearing和ratotion。用于平移,产生透视变换。所以可以理解成仿射等是透视变换的特殊形式。经过透视变换之后的图片通常不是平行四边形(除非映射视平面和原来平面平行的情况)。

简单的看一个正方形到四边形的变换:
变换的4组对应点可以表示成:

根据变换公式得到:

定义几个辅助变量:

都为0时变换平面与原来是平行的,可以得到:

不为0时,得到:

求解出的变换矩阵就可以将一个正方形变换到四边形。反之,四边形变换到正方形也是一样的。于是,我们通过两次变换:四边形变换到正方形+正方形变换到四边形就可以将任意一个四边形变换到另一个四边形。

 opencv中相关API函数:

计算透视矩阵(通过输入和输出图像中两组点计算透视矩阵):

findHomography( InputArray srcPoints, InputArray dstPoints,
                               OutputArray mask, int method = 0, double ransacReprojThreshold = 3 );

 图像的透视变换(利用透视矩阵对图像进行透视变换):

warpPerspective( InputArray src, OutputArray dst,
                                   InputArray M, Size dsize,
                                   int flags = INTER_LINEAR,
                                   int borderMode = BORDER_CONSTANT,
                                   const Scalar& borderValue = Scalar());

 点的透视变换(利用透视矩阵对点进行透视变换):

perspectiveTransform(InputArray src, OutputArray dst, InputArray m );

鼠标回调函数:

setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);

 CV_EVENT_LBUTTONUP  (鼠标左键响应事件)
 CV_EVENT_RBUTTONUP (鼠标右键响应事件)

#include<opencv2\opencv.hpp>
#include<opencv2\xfeatures2d.hpp>
using namespace cv;
using namespace xfeatures2d;
using namespace std
;
vector<Point2f> srcTri(4);
vector<Point2f> dstTri(4);
int clickTimes = 0;  //在图像上单击次数
Mat src,dst;
Mat imageWarp;
void onMouse(int event, int x, int y, int flags, void *utsc);

	int main(int argc, char *argv[])
	{
		src = imread("2.jpg");
		namedWindow("src", CV_WINDOW_AUTOSIZE);
		imshow("src", src);	
		setMouseCallback("src", onMouse);
		waitKey();
		return 0;
	}
	void onMouse(int event, int x, int y, int flags, void *utsc)
	{
		if (event == CV_EVENT_LBUTTONUP)   //响应鼠标左键事件
		{
			circle(src, Point(x, y), 2, Scalar(0, 0, 255), 2);  //标记选中点
			imshow("wait ", src);
			srcTri[clickTimes].x = x;
			srcTri[clickTimes].y = y;
			clickTimes++;
		}
		if (clickTimes == 4)
		{
			dstTri[0].x = 0;
			dstTri[0].y = 0;	
			dstTri[1].x = 282;
			dstTri[1].y = 0;
			dstTri[2].x = 282 ;
			dstTri[2].y = 438;
			dstTri[3].x = 0;
			dstTri[3].y = 438;
					
			Mat H = findHomography(srcTri, dstTri, RANSAC);//计算透视矩阵
			warpPerspective(src, dst, H, Size(282, 438));//图像透视变换
			imshow("output", dst);
		}
	}

参考文献:https://blog.csdn.net/xiaowei_cqu/article/details/26471527

猜你喜欢

转载自blog.csdn.net/qq_24946843/article/details/82697364
今日推荐