从直观的角度看,仿射变换和透视变换的最大区别是:一个平行四边形,经过仿射变换后依然是平行四边形;而经过透视变换后只是一个四边形(不再平行了)。
仿射变换
仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换,是一个线性变换,该过程只发生旋转和平移过程。因此,一个平行四边形经过仿射变换后还是一个平行四边形。
所以,仿射= 旋转 + 平移
仿射变换矩阵为:
其中,(x,y)是原图坐标,(x’,y’)是变换后的坐标;m11,m12,m21,m22为旋转量,m13,m23为平移量。所以仿射变换矩阵实际为2*3的矩阵,以上只是齐次性,为了方便简洁表达旋转和平移,因此,仿射变换为线性变换。
在opencv中,实现仿射变换的函数为:
- warpAffine(src,dst,M,(cols,rows))
- src:输入图像
- dst:输出图像
- M:2*3的仿射变换矩阵
- (cols,rows):输出图像的行数和列数
以下用python编程语言,opencv函数库简单实现一下仿射变换,以下程序实现把一张图片顺时针旋转45°,向左平移200个像素点,向下平移30个像素点,该过程的仿射变换矩阵为:
import cv2 as cv
import numpy as np
src = cv.imread("Google.jpg")
rows,cols = src.shape[0:2]
M = np.array([[np.cos(np.pi/4),np.sin(-np.pi/4),500],[np.sin(np.pi/4),np.cos(np.pi/4),30]]) #顺时针旋转45度,向左平移200,向下平移30
dst = cv.warpAffine(src,M,(2*cols, 2*rows))#把输出图像的大小改为输入图像的两倍
cv.imshow("src",src)
cv.imshow("dst",dst)
cv.imwrite("affine.jpg", dst)
cv.waitKey(0)
输入图像src:
输出图片dst:
透视变换
透视变换是把一个图像投影到一个新的视平面的过程,该过程包括:把一个二维坐标系转换为三维坐标系,然后把三维坐标系投影到新的二维坐标系。该过程是一个非线性变换过程,因此,一个平行四边形经过透视变换后只得到四边形,但不平行。
透视变换矩阵为:
其中,(x,y)是原图坐标,(x’,y’)是变换后的坐标;m11,m12,m21,m22,m31,m32为旋转量,m13,m23,m33为平移量。因为透视变换是非线性的,所以不能齐次性表示;透视变换矩阵为3*3。
在opencv中,实现透视变换的函数为:
- warpPerspective(src,dst,H,(cols,rows))
- src:输入图像
- dst:输出图像
- H:3*3的仿射变换矩阵
- (cols,rows):输出图像的行数和列数
程序实现跟仿射变换差不多,这里不再展示。
总结
仿射变换常用于旋转和平移等图像处理操作,原理较简单。而透视变换的实际应用较大,如视角纠正,全景拼接等。