几何变换——放大、镜像、平移、旋转、透视、仿射
1.扩展缩放
缩放只是调整图像大小.为此,OpenCV附带了一个函数cv.resize()
.cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
- 对shrinking,优选的interpolation方法:
cv2.INTER_AREA
该方法可以避免波纹的出现 - 对zooming,优选的interpolation方法:
cv2.INTER_CUBIC
和cv2.INTER_LINEAR
(默认)
import cv2 import numpy as np img = cv2.imread('test.jpg') # 下面的None 本应该是输出图像的尺寸,但是因为后边我们设置了缩放因子 # 因此这里为None 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) while True: cv2.imshow('res', res) cv2.imshow('img', img) key = cv2.waitKey(1) if key == 27: break cv2.destroyAllWindows()
示例图片:
效果如图所示:
2.平移
平移就是将对象换一个位置。如果你要沿(x,y)方向移动,移动的距离是(tx,ty),你可以以下面的方式构建移动矩阵:
你可以使用Numpy 数组构建这个矩阵(数据类型是np.float32),然后把它传给函数cv2.warpAffine()。
import cv2 import numpy as np img = cv2.imread('test.jpg') imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] mode = imgInfo[2] dst = np.zeros(imgInfo, np.uint8) for i in range(height): for j in range(width-100): dst[i, j+100] = img[i, j] cv2.imshow('image', dst) cv2.waitKey(0)
结果如下所示:
警告:函数cv2.warpAffine() 的第三个参数的是输出图像的大小,它的格式应该是图像的(宽,高)。应该记住的是图像的宽对应的是列数,高对应的是行数。
3.旋转
为了构建这个旋转矩阵,OpenCV 提供了一个函数:cv2.getRotationMatrix2D。
下面的例子是在不缩放的情况下将图像旋转90 度。
import cv2 import numpy as np img = cv2.imread('test.jpg',0) rows,cols = img.shape # 这里的第一个参数为旋转中心,第二个为旋转角度,第三个为旋转后的缩放因子 # 可以通过设置旋转中心,缩放因子,以及窗口大小来防止旋转后超出边界的问题 M = cv2.getRotationMatrix2D((cols/2, rows/2),90, 0.6) #第三个参数是输出图像的尺寸中心 dst = cv2.warpAffine(img, M, (2*cols, 2*rows)) while True: cv2.imshow('img', dst) key = cv2.waitKey(1) if key==27: break cv2.destroyAllWindows()
效果如图所示:
4.仿射变换
在仿射变换中,原图中所有的平行线在结果图像中同样平行。为了创建这个矩阵我们需要从原图像中找到三个点以及他们在输出图像中的位置。然后cv2.getAffineTransform 会创建一个2x3 的矩阵,最后这个矩阵会被传给函数cv2.warpAffine。
import cv2 import numpy as np img = cv2.imread('test.jpg',1) cv2.imshow('src',img) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] deep = imgInfo[2] matSrc = np.float32([[0,0],[0,height-1], [width-1, 0]])# 需要注意的是 行列 和 坐标 是不一致的 matDst = np.float32([[50,50],[100, height-50], [width-200, 100]]) matAffine = cv2.getAffineTransform(matSrc, matDst) dst = cv2.warpAffine(img, matAffine, (height,width)) cv2.imshow('image',dst) cv2.waitKey(0) cv2.destroyAllWindows()
结果如图所示:
5.透视变换
对于视角变换,我们需要一个3x3 变换矩阵。在变换前后直线还是直线。要构建这个变换矩阵,你需要在输入图像上找4 个点,以及他们在输出图像上对应的位置。这四个点中的任意三个都不能共线。这个变换矩阵可以有函数cv2.getPerspectiveTransform() 构建。然后把这个矩阵传给函数cv2.warpPerspective。
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('test.jpg',1) row,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()
效果如图所示:
6.镜像变换
import cv2 import numpy as np img = cv2.imread('test.jpg',1) cv2.imshow('src',img) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] deep = imgInfo[2] dst = np.zeros([height*2, width, deep], np.uint8) for i in range(height): for j in range(width): dst[i, j] = img[i, j] dst[height*2-i-1, j] = img[i,j] for i in range(width): dst[height, i]= (0, 0, 255) cv2.imshow('image', dst) cv2.waitKey(0) cv2.destroyAllWindows()
效果如图所示:
学以致用,知行合一