opencv中的图像变换

这篇文章主要为记录自己在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_101cv2.BORDER_DEFAULT:反射边缘像素,但不复制边缘像素。

borderValue:borderModecv2.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")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值