这篇文章主要为记录自己在opencv中用到的一些图像变换操作
1. 图像的缩放
opencv中提供了图像缩放的resize函数,用于调整图像的大小。这个函数可以将图像缩放到指定的尺寸,或者按给定的比例进行缩放。
import cv2
import numpy as np
from PIL import Image
# 导入图像
img_st = cv2.imread("img/st.jpeg")
print(img_st.shape) # (535, 640, 3) 图像尺寸为(640, 535)
# 缩放图像
"""
src:输入图像。
dsize:输出图像的尺寸,格式为 (width, height)。如果 dsize 为 (0, 0),则 fx 和 fy 必须是非零值。
fx:沿水平方向的缩放因子。如果 fx 为 0,则使用 dsize 中的宽度。
fy:沿垂直方向的缩放因子。如果 fy 为 0,则使用 dsize 中的高度。
● interpolation:插值方法。常用的插值方法包括:
○ cv2.INTER_NEAREST:最近邻插值。
○ cv2.INTER_LINEAR:双线性插值(默认)。
○ cv2.INTER_AREA:基于区域的插值。
○ cv2.INTER_CUBIC:三次样条插值。
○ cv2.INTER_LANCZOS4:Lanczos 插值。
"""
img_st_resize = cv2.resize(img_st, (640, 480))
print(img_st_resize.shape) # (480, 640, 3) 图像尺寸为(640, 480)
cv2.imshow("st_resize" ,img_st_resize)
cv2.waitKey(0)
cv2.destroyWindow("st_resize")
2. 图像的旋转
opencv中提供了图像旋转的rotate函数,用于进行图像的旋转。这个函数可以将图像顺时针或逆时针旋转 90 度、180 度或 270 度。
import cv2
import numpy as np
from PIL import Image
# 导入图像
img_st = cv2.imread("img/st.jpeg")
print(img_st.shape) # (535, 640, 3) 图像尺寸为(640, 535)
# 旋转图像
"""
src:输入图像。
rotateCode:旋转代码,指定旋转的方向。可用的旋转代码包括:
○ cv2.ROTATE_90_CLOCKWISE:顺时针旋转 90 度。
○ cv2.ROTATE_180:旋转 180 度。
○ cv2.ROTATE_90_COUNTERCLOCKWISE:逆时针旋转 90 度(等同于顺时针旋转 270 度)。
"""
img_st_rotate = cv2.rotate(img_st, cv2.ROTATE_90_CLOCKWISE)
cv2.imshow("st_rotate" ,img_st_rotate)
cv2.waitKey(0)
cv2.destroyWindow("st_rotate")
3. 图像平移
使用 cv2.warpAffine 函数可以使图像进行平移,不过在使用此函数之前,得先获取平移矩阵M,平移矩阵M的形状要求:
其中tx表示水平位移的距离, ty表示垂直位移的距离,而且需要注意,转换矩阵的元素类型必须是float32或float64
import numpy as np
M = np.float32[[1, 0, 40], [0, 1, 40]] # 表示水平位移40, 垂直位移40
当有了平移矩阵之后,就可以对图像进行平移操作了
cv2.warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
参数说明:
src:输入图像
M:平移矩阵
dsize:输出图像的尺寸 (宽度, 高度)。
flags:插值方式
borderMode:边界填充模式,默认为 cv2.BORDER_CONSTANT,
此外还有:
cv2.BORDER_CONSTANT
:常数填充。cv2.BORDER_REPLICATE
:复制边缘像素。cv2.BORDER_REFLECT
:反射边缘像素。cv2.BORDER_WRAP
:平铺边缘像素。cv2.BORDER_REFLECT_101
或cv2.BORDER_DEFAULT
:反射边缘像素,但不复制边缘像素。
borderValue:当 borderMode
为 cv2.BORDER_CONSTANT
时使用的常数值,默认为 0。
import cv2
import numpy as np
from PIL import Image
# 导入图像
img_st = cv2.imread("img/st.jpeg")
print(img_st.shape) # (535, 640, 3) 图像尺寸为(640, 535)
# 创建变换矩阵M
# M 要求 shape=(2, 3)
M =np.float32([[1, 0, 100],[0, 1, 100]]) # 表示水平位移100, 垂直位移100
# 图像平移
img_st_warpAffine = cv2.warpAffine(img_st, M, (640, 535))
# 将原图和做过变换的图像水平堆叠, 水平堆叠要求两数组 0 轴长度相同
img = np.hstack((img_st, img_st_warpAffine))
cv2.imshow("img" ,img)
cv2.waitKey(0)
cv2.destroyWindow("img")
4. 自由旋转
使用 cv2.getRotationMatrix2D 获取旋转矩阵,该函数用于成一个 2x3 的旋转矩阵。搭配 cv2. warpAffine 就可以做到对图像进行自由旋转。
cv2.getRotationMatrix2D(center, angle, scale)
参数说明:
center:旋转的中心点,通常为图像的中心,格式为 (x, y)
。
angle:旋转的角度,正值表示逆时针旋转,负值表示顺时针旋转。
scale:缩放因子,1.0 表示不缩放。
import cv2
import numpy as np
from PIL import Image
# 导入图像
img_st = cv2.imread("img/st.jpeg")
print(img_st.shape) # (535, 640, 3) 图像尺寸为(640, 535)
# 获取旋转矩阵
M_RotationMatrix2D = cv2.getRotationMatrix2D((0, 0), -45, 1)
print(M_RotationMatrix2D)
print(M_RotationMatrix2D.shape) # (2, 3) 是一个二行三列的矩阵, 与平移矩阵的形状一样
"""
[[ 3.061617e-17 5.000000e-01 0.000000e+00]
[-5.000000e-01 3.061617e-17 0.000000e+00]]
"""
# 图像平移旋转
img_st_rotate_affine = cv2.warpAffine(img_st, M_RotationMatrix2D, (640, 535))
# 将原图和做过变换的图像水平堆叠
img = np.hstack((img_st, img_st_rotate_affine))
cv2.imshow("img" ,img)
cv2.waitKey(0)
cv2.destroyWindow("img")
5. 仿射变换
使用 cv2.getAffineTransform 获取仿射变换矩阵,该函数用于计算从一组点到另一组点的仿射变换矩阵。搭配 cv2. warpAffine 就可以做到对图像进行仿射变换。这种变换可以用来对图像进行平移、旋转、缩放以及轻微的倾斜。仿射变换保持了平行线和平行性,但可能改变线段长度和角度。
cv2.getAffineTransform(src, dst)
参数说明:
src:源点集,是一个 3x2 的 NumPy 数组,其中每一行代表一个点的 x 和 y 坐标。这三个点在原始图像中。
dst:目标点集,也是一个 3x2 的 NumPy 数组,与 src
对应,表示 src
中的点经过变换后应该到达的位置。
import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
# 导入图像
img_st = cv2.imread("img/st.jpeg")
print(img_st.shape) # (535, 640, 3) 图像尺寸为(640, 535)
# 使用matplotlib.pyplot 将图片的坐标轴显示
# plt.imshow(img_st)
# plt.show()
# 定义一组需要仿射变换的坐标 —— 一个float32或float64的(3, 2)的坐标数组, 也就是需要三个坐标
pt1 = np.float32([[100, 100], [50, 500], [550, 510]])
# 定义一组最终仿射变换后的坐标 —— 一个float32或float64的(3, 2)的坐标数组, 也就是需要三个坐标
pt2 = np.float32([[0, 0], [0, 540], [610, 540]])
# 获取仿射变换矩阵
M_AffineTransform = cv2.getAffineTransform(pt1, pt2)
print(M_AffineTransform)
"""
[[ 1.21695761e+00 1.52119701e-01 -1.36907731e+02]
[-2.69326683e-02 1.34663342e+00 -1.31970075e+02]]
"""
print(M_AffineTransform.shape) # (2, 3) 是一个二行三列的矩阵, 与平移矩阵的形状一样
# 图像平移旋转
img_st_affinetransform = cv2.warpAffine(img_st, M_AffineTransform, (640, 535))
# 将原图和做过变换的图像水平堆叠
img = np.hstack((img_st, img_st_affinetransform))
cv2.imshow("img" ,img)
cv2.waitKey(0)
cv2.destroyWindow("img")
6. 透视变换
使用 cv2.getPerspectiveTransform 获取透视变换矩阵,该函数用于计算从一组点到另一组点的透视变换矩阵。搭配 cv2. warpAffine 就可以做到对图像进行透视变换。透视变换是一种更通用的变换,它不仅可以处理平移、旋转和缩放,还可以处理图像的倾斜和视角变化。透视变换通常用于校正图像中的透视失真,例如将一张倾斜的照片校正为正面视图。
cv2.getPerspectiveTransform(src, dst)
参数说明:
src:源点集,是一个 4x2 的 NumPy 数组,其中每一行代表一个点的 x 和 y 坐标。这四个点在原始图像中。
dst:目标点集,也是一个 4x2 的 NumPy 数组,与 src
对应,表示 src
中的点经过变换后应该到达的位置。
import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
# 导入图像
img_st = cv2.imread("img/st.jpeg")
print(img_st.shape) # (535, 640, 3) 图像尺寸为(640, 535)
# 使用matplotlib.pyplot 将图片的坐标轴显示
# plt.imshow(img_st)
# plt.show()
# 定义一组需要透视变换的坐标 —— 一个float32或float64的(3, 2)的坐标数组, 也就是需要三个坐标
pt1 = np.float32([[50, 20], [610, 80], [50, 500], [550, 510]])
# 定义一组透视仿射变换后的坐标 —— 一个float32或float64的(3, 2)的坐标数组, 也就是需要三个坐标
pt2 = np.float32([[0, 0], [620, 0], [0, 520], [620, 520]])
# 获取透视变换矩阵
M_PerspectiveTransform = cv2.getPerspectiveTransform(pt1, pt2)
print(M_PerspectiveTransform)
"""
[[ 9.82137500e-01 4.49990728e-18 -4.91068750e+01]
[-1.01112303e-01 9.43714825e-01 -1.38186814e+01]
[-1.53301470e-04 -2.42427099e-04 1.00000000e+00]]
"""
print(M_PerspectiveTransform.shape) # (3, 3) 透视变换矩阵是一个三行三列的矩阵
# 图像透视变换
img_st_perspectivetransform = cv2.warpPerspective(img_st, M_PerspectiveTransform, (640, 535))
# 将原图和做过变换的图像水平堆叠
img = np.hstack((img_st, img_st_perspectivetransform))
cv2.imshow("img" ,img)
cv2.waitKey(0)
cv2.destroyWindow("img")