缩放
使用 cv.resize()函数
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img, None, fx=2, fy=2, interpolation=cv.INTER_CUBIC)
# 或者
height, width = img.shape[:2]
res = cv.resize(img, (2*width, 2*height), interpolation=cv.INTER_CUBIC)
以上代码示例演示了两种调整图像大小的方法:通过指定缩放比例 fx 和 fy 或直接指定目标图像的高度和宽度来调整图像的大小
在 OpenCV 的 resize() 函数中,可以使用不同的插值方法来进行图像的调整。下面列举了常用的几种插值方法及其效果和适用场景:
-
cv.INTER_NEAREST(最近邻插值):最近邻插值方法会将目标像素的值设置为最接近其相应位置的原始像素的值。该方法执行速度快,适用于对速度要求较高、不关注平滑效果的场景。
-
cv.INTER_LINEAR(双线性插值):双线性插值方法会利用原始图像中最接近目标像素位置的四个像素的加权平均值作为目标像素的值。这种方法可以得到平滑的结果,适用于一般的图像缩放任务。
-
cv.INTER_CUBIC(双立方插值):双立方插值方法会利用原始图像中最接近目标像素位置的 16 个像素的加权平均值来计算目标像素的值。它比双线性插值更精确,可以保留更多的细节,适用于对图像质量要求较高的任务。
-
cv.INTER_AREA(区域插值):区域插值方法是一种特殊的插值方法,主要用于图像缩小操作。它根据目标像素与原始图像像素的关系,在原始图像的局部区域内进行像素值的平均采样。该方法适用于图像缩小时要保留细节的场景。
根据图像处理的需求和场景,可以选择合适的插值方法来调整图像大小。最近邻插值适用于速度要求高、不关注平滑效果的场景;双线性插值是一种常用的默认选择,可以在速度和质量之间取得平衡;双立方插值能够提供更高质量的结果,但计算成本也较高;区域插值适用于图像缩小时需要保留细节的场景。
平移
使用OpenCV 的 cv.warpAffine 函数进行平移变换
import cv2
import numpy as np
# 读取图像
image = cv2.imread('input.jpg')
# 设置平移的偏移量
t_x = 100
t_y = 50
# 创建平移矩阵
M = np.float32([[1, 0, t_x], [0, 1, t_y]])
# 应用平移变换
output = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
# 显示结果
cv2.imshow('Translated Image', output)
cv2.waitKey(0)
cv2.destroyAllWindows()
我们首先读取输入图像,并设置了在 x 和 y 方向上的偏移量 t_x 和 t_y。然后,通过创建一个平移矩阵 M,其中第一行表示 x 方向上的平移值,第二行表示 y 方向上的平移值。
最后,我们使用 cv2.warpAffine 函数应用平移变换到输入图像上。将平移矩阵 M、输入图像的尺寸以及输出图像的尺寸作为参数传递给该函数。
旋转
使用旋转变化矩阵
import cv2
# 读取图像
img = cv2.imread('messi5.jpg', 0)
# 获取图像尺寸
rows, cols = img.shape
# 计算变换矩阵
center = ((cols-1) / 2.0, (rows-1) / 2.0)
angle = 90
scale = 1
alpha = scale * np.cos(np.deg2rad(angle))
beta = scale * np.sin(np.deg2rad(angle))
M = np.float32([[alpha, beta, (1-alpha) * center[0] - beta * center[1]],
[-beta, alpha, beta * center[0] + (1-alpha) * center[1]]])
# 应用旋转变换
dst = cv2.warpAffine(img, M, (cols, rows))
# 显示结果
cv2.imshow('Rotated Image', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
其中,OpenCV提供了一个函数cv.getRotationMatrix2D可以帮我们找到旋转矩阵
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 和 rows-1 是坐标限制
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))
该示例将图像相对于中心旋转90度而没有任何缩放比例。
仿射变换
在仿射变换中,原始图像中的所有平行线在输出图像中仍将平行。为了找到变换矩阵,我们需要
输入图像中的三个点及其在输出图像中的对应位置。然后cv.getAffineTransform将创建一个2x3
矩阵,该矩阵将传递给cv.warpAffine。
img = cv.imread('drawing.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 = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
透视变换
对于透视变换,您需要3x3变换矩阵。即使在转换后,直线也将保持直线。要找到此变换矩阵,您
需要在输入图像上有4个点,在输出图像上需要相应的点。在这四个点中,其中三个不应共线。然
后可以通过函数cv.getPerspectiveTransform找到变换矩阵。然后将cv.warpPerspective应
用于此3x3转换矩阵。
img = cv.imread('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 = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.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()