本教程将学习如下内容:
- 学习对图像应用不同的几何变换,如平移、旋转、仿射变换等
- 介绍关键函数
cv2.getPerspectiveTransform
转换
OpenCV提供了两个转换函数,cv2.warpAffine
和cv2.warpPerfective
,可以使用它们进行各种转换。
cv2.warpAffine
采用2x3的变换矩阵,而cv2.warpEspective
采用3x3的变换基质作为输入。
缩放比例
缩放只是调整图像的大小。OpenCV为此提供了一个函数cv2.resize()
。
图像的大小可以手动指定,也可以指定缩放因子。使用了不同的插值方法。
首选的插值方法是cv2.INTER_AREA
用于缩小,cv2.INTER_CUBIC
(慢速)和cv2.INTER_LINEAR
用于缩放。
默认情况下,用于调整大小的插值方法为cv2.INTER_LINEAR
,可以通过以下任一方法调整输入图像的大小:
import cv2
import numpy as np
img = cv2.imread('/data/cvdata/messi5.jpg')
res = cv2.resize(img,None,fx=2, fy=2, interpolation = cv2.INTER_CUBIC)
或者
height, width = img.shape[:2]
res = cv2.resize(img,(2*width, 2*height), interpolation = cv2.INTER_CUBIC)
import cv2
import numpy as np
img = cv2.imread('/data/cvdata/messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))
# cv2.imshow('img',dst)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(dst)
<matplotlib.image.AxesImage at 0x7f38001c9190>
警告:
cv2.warpAffine()
函数的第三个参数是输出图像的大小,其形式应为(width,height)。记住width=列数,height=行数。
请看下面的结果:
旋转
将图像旋转一个角度 $\theta$, 通过以下形式的变换矩阵来实现:
$$\begin{aligned} M = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix} \end{aligned}$$
但OpenCV提供了可调整旋转中心且支持缩放的旋转功能, 因此可以在任意指定位置进行旋转。修正后的变换矩阵如下:
$$\begin{aligned} \begin{bmatrix} \alpha & \beta & (1- \alpha ) \cdot center.x - \beta \cdot center.y \\ - \beta & \alpha & \beta \cdot center.x + (1- \alpha ) \cdot center.y \end{bmatrix} \end{aligned}$$
其中:
$$\begin{aligned} \begin{array}{l} \alpha = scale \cdot \cos \theta , \\ \beta = scale \cdot \sin \theta \end{array} \end{aligned}$$
为了找到这个变换矩阵,OpenCV提供了一个函数cv2.getRotationMatrix2D
。
请查看以下示例,该示例在不进行任何缩放的情况下将图像相对于中心旋转90度。
# img = cv2.imread('/data/cvdata/messi5.jpg',0)
rows,cols = img.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.imshow(dst)
<matplotlib.image.AxesImage at 0x7f37fbe86210>
# img = cv2.imread('/data/cvdata/drawing.png')
import cv2
img = cv2.imread('/data/cvdata/cards.png')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()
img = cv2.imread('/data/cvdata/sudoku.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()