简述

在图像处理中,因为镜头角度等原因,容易导致图像出现倾斜、变形等情况,为了方便后续处理我们常常需要进行图像矫正,其中主要技术原理是两种变换类型--仿射变换(Affine Transformation)和透视变换(Perspective Transformation)。

详解

仿射变换是二维坐标间的线性变换,故而变换后的图像仍然具有原图的一些性质,包括“平直性”以及“平行性”,常用于图像翻转(Flip)、旋转(Rotations)、平移(Translations)、缩放(Scale operations)等,具体到代码应用可以参见OpenCV官方介绍。

但是仿射变换不能矫正一些变形,如矩形区域的部分发生变化最终变成梯形,这时候矫正就需要用到透视变换。透视变换(Perspective Transformation),又称投影映射(Projective Mapping)、投射变换等,是三维空间上的非线性变换,即通过一个3x3的变换矩阵将原图投影到一个新的视平面,在视觉上的直观表现就是产生或消除了远近感。

步骤

1、首先第一步,先获取透视变换的变换矩阵,通过下面这个方法来获取:

Mat getPerspectiveTransform(const Point2f src[], const Point2f dst[])

输入原始图像和变换之后的图像的4组对应点,便可以得到变换矩阵。

2、透视变换。图像的透视变换由以下函数完成(该函数是针对图像的包装,其本质调用cv::perspectiveTransform进行向量坐标的变换):

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

src是输入图像,dst是输出图像,M是3x3变换矩阵,dsize是输出图像的大小,flags指定像素插补方法以及矩阵倒置标志cv::WARP_INVERSE_MAP,CV_INTER_LINEAR填充所有目标图像的像素,如果部分图像落在边界外,那么它们的值将被设定为fillval
borderMode指定边沿像素的推算模式,其中BORDER_CONSTANT指边沿像素用borderValue替换,因为默认是0,所以我们变换后的图像边界可能会出现黑边,此时可以指定BORDER_REPLICATE对边界像素进行复制。

实例:

int TransforMatrix(vector<cv::Point2f> screenPoints,vector<cv::Point2f> wallPoints)
{
	int screenPts_Len = screenPoints.size();
	int wallPts_Len = wallPoints.size();
	if (screenPts_Len != 4  || wallPts_Len != 4)
	{
		return PROJ_FAIL;
	}
	
	//原始图像四角点
	cv::Point2f *pts_src;
	//目标图像四角点
	cv::Point2f *pts_dst;	
	//3 X 3变换矩阵
	Mat m_MapMatrix;

	//【0】映射对应点对
	for (int k = 0; k < 4; k++)
	{
		pts_src[k] = wallPoints[k];
		pts_dst[k] = screenPoints[k];
	}

	//【1】求得映射矩阵 m_MapMatrix 是3 x 3 变换矩阵
	m_MapMatrix = getPerspectiveTransform(pts_src, pts_dst);
	
	//【2】透视变换
	//m_foreImg 与 screenImg大小相同
	//m_dstWidth、m_dstHeight指目标函数宽、高
	warpPerspective(m_foreImg, screenImg, m_MapMatrix, Size(m_dstWidth, m_dstHeight), CV_INTER_LINEAR , BORDER_REPLICATE);
	
        //screenImg为转换后的图像
	return PROJ_OK;
}