图像的仿射变换与透视变换opencv

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012507022/article/details/52899936

        图像有两种常见的几何转换:一种是基于2×3矩阵进行的变换,也叫仿射变换;另一种是基于3×3矩阵的变换,又称透视变换。可以把透视变换当作一个三维平面被一个特定观察者感知的计算方法,而该观察者也许不是垂直观测该平面。

1.仿射变换

仿射变换代表是两幅图像之间的映射关系,可以表达为乘以一个矩阵再加上一个向量的形式;通常使用2×3的矩阵来表示仿射变换。


仿射变换可表达为Y=A×X+B的形式,在效果上等价于将向量X拓展成X,并且只是将X左乘T,即:


   仿射变换可以表达成以下形式。一个平面内的任意平行四边形ABCD可以被仿射变换映射为另一个平行四边形ABCD。如果这些平行四边形的面积不等于0,这个隐含的仿射变换就被两个平行四边形唯一定义。可以把仿射变换想象成把一幅图像画到一个胶板上,在胶板的角上任意推拉改变形状得到不同类型的平行四边形。

2.透视变换

仿射变换可以将图像转换为平行四边形,透视变换提供了更大的灵活性,一个透视变换可以将矩形转变为梯形,平行四边形也是梯形,所以仿射变换是透视变换的子集。设透视变换矩阵:


则,透视变换的原图像与目标图像的映射关系为:

 \texttt{dst} (x,y) =  \texttt{src} \left ( \frac{M_{11} x + M_{12} y + M_{13}}{M_{31} x + M_{32} y + M_{33}} ,     \frac{M_{21} x + M_{22} y + M_{23}}{M_{31} x + M_{32} y + M_{33}} \right )

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;

#define WINDOW_NAME1 "Original Image"					 
#define WINDOW_NAME2 "Affine transformation"             
#define WINDOW_NAME3 "Perspective transformation"     

int main(  )
{
	bool  Affine=true;   
	bool  Perspective=true;

	Mat srcImage, dstImage_Aff, dstImage_Per;

	//加载源图像并作一些初始化
	srcImage = imread( "lena.png", 1 );
	if(!srcImage.data ) { printf("读取图片错误\n"); return false; } 
	dstImage_Aff = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());
	dstImage_Per = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());

	if(Affine){
		//仿射变换三个点的映射关系
		Point2f srcTriangle[3];
		Point2f dstTriangle[3];
		Mat AffMat( 2, 3, CV_32FC1 );  //仿射变换矩阵
		//设置源图像和目标图像上的三组点以计算仿射变换
		srcTriangle[0] = Point2f( 0,0 );  //原始图像的左上点
		srcTriangle[1] = Point2f( (srcImage.cols), 0 ); //原始图像的右上点
		srcTriangle[2] = Point2f( 0, (srcImage.rows )); //原始图像的左下点

		dstTriangle[0] = Point2f( (srcImage.cols*0.0), (srcImage.rows*0.5));
		dstTriangle[1] = Point2f( (srcImage.cols*0.5), (srcImage.rows*0.0));
		dstTriangle[2] = Point2f( (srcImage.cols*0.5), (srcImage.rows*1.0));
		//求得仿射变换矩阵并计算的仿射变换
		AffMat = getAffineTransform( srcTriangle, dstTriangle );
		//Output affine transformation matrix
		cout<<"affine transformation matrix:\n"<<AffMat<<endl;
		warpAffine(srcImage, dstImage_Aff, AffMat,dstImage_Aff.size());

		imshow( WINDOW_NAME2, dstImage_Aff );
	}
	if(Perspective){
		//投影变换四个点的映射关系
		Point2f srcQuadrilateral[4];
		Point2f dstQuadrilateral[4];
		//定义一些Mat变量
		Mat PerMat( 3, 3, CV_32FC1 );  //透视变换矩阵
		//设置源图像和目标图像上的四组点以计算透视变换
		srcQuadrilateral[0] = Point2f(0,               0);  //原始图像的左上点
		srcQuadrilateral[1] = Point2f((srcImage.cols), 0); //原始图像的右上点
		srcQuadrilateral[2] = Point2f(0,                (srcImage.rows )); //原始图像的左下点
		srcQuadrilateral[3] = Point2f((srcImage.cols ), (srcImage.rows )); //原始图像的左下点

		dstQuadrilateral[0] = Point2f( (srcImage.cols*0.0),(srcImage.rows*0.5));
		dstQuadrilateral[1] = Point2f( (srcImage.cols*0.5),(srcImage.rows*0.0));
		dstQuadrilateral[2] = Point2f( (srcImage.cols*0.5),(srcImage.rows*1.0));
		dstQuadrilateral[3] = Point2f( (srcImage.cols*1.0),(srcImage.rows*0.5));

		//求得透视变换矩阵并计算的透视变换
		PerMat = getPerspectiveTransform( srcQuadrilateral, dstQuadrilateral );
		//Output perspective transformation matrix
		Mat PerMat2;
		PerMat.convertTo(PerMat2, CV_32F);
		cout<<"perspective transformation matrix:\n"<<PerMat2<<endl;
		warpPerspective(srcImage, dstImage_Per, PerMat,dstImage_Per.size());

		imshow( WINDOW_NAME3, dstImage_Per );
	}

	//显示结果
	imshow( WINDOW_NAME1, srcImage );
	waitKey(0);

	return 0;
}
更多资源:http://blog.csdn.net/xiaowei_cqu/article/details/26471527
      http://m.blog.csdn.net/article/details?id=51355600
      http://blog.csdn.net/u012380663/article/details/43273527





 

猜你喜欢

转载自blog.csdn.net/u012507022/article/details/52899936