pip install opencv-python
import cv2
import numpy as np
读取与保存
imread读取之后的东西都是用np数组保存的,反之也是。保存的形式是[H*W*(BGR)]
>>> img = cv2.imread("./test.png")
>>> img.shape
(288, 512, 3)
image_3 = cv2.imread(‘image_3.png’, cv2.IMREAD_UNCHANGED) # 带有透明通道的png图片要加额外参数
cv2.imwrite("./test.png", img)
图像的基本操作
改变通道
无视后面的.shape
,纯粹是为了输出
>>> cv2.cvtColor(img, cv2.COLOR_BGR2RGB).shape
(288, 512, 3) # 改为RGB
>>> cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).shape
(288, 512) # 改为灰度图像
>>> img_alpha = np.dstack([img, np.ones((img.shape[0], img.shape[1])) * 255])
>>> img_alpha.shape
(288, 512, 4) # 增加透明通道
尺寸改变
拉伸
resized_image_2 = cv2.resize(image_2, dsize=(512, 288)) # 宽、高
填充
区别于css,它的四个padding参数的顺序是top, bottom, left, right
mj = cv2.copyMakeBorder(
mj,
max(0, (mj_h_r - mj_h) // 2),
max(0, (mj_h_r - mj_h) // 2),
max(0, (mj_w_r - mj_w) // 2),
max(0, (mj_w_r - mj_w) // 2),
borderType=cv2.BORDER_CONSTANT,
value=(0, 0, 0, 0),
)
替换/裁切
前面说到,cv2读进来的图像就是np数组存储,裁切或者替换其实就是删去/替换数组元素
image_1[50:150, 50:150] = resized_image_2 # 替换,注意即使有一个维度不替换,也不能少写或者省略索引
image = image_1[50:150, 50:150] # 这个随便吧,符合np语法就行
旋转
先定义一个旋转矩阵,旋转中心、旋转角度(360度制)、旋转放缩
M = cv2.getRotationMatrix2D(
(max(mj_w_r / 2, mj_w / 2), max(mj_h_r / 2, mj_h / 2)),
angle=mj_angle,
scale=1,
)
应用这个旋转矩阵,warp这个函数根据参数,会包裹住被旋转的图像,分别是被旋转图像,旋转矩阵,旋转后图片大小,填充值
mj = cv2.warpAffine(
mj, M, (max(mj_w_r, mj_w), max(mj_h_r, mj_h)), borderValue=(0, 0, 0, 0)
)
替换带透明通道的图片技巧
alpha通道的255代表不透明,0代表透明
mj_not_alpha = 255 - mj[:, :, 3] # 取反透明通道,标记背景需要被无视的部分
mj_not_alpha = np.repeat(mj_not_alpha[:, :, np.newaxis], 4, 2) # 因为要覆盖BGR三个通道
# 背景被覆盖的部分*0,然后加上覆盖值;不被覆盖的部分*1,然后加上0,0,0
img[mj_y : mj_y + mj_h_r, mj_x : mj_x + mj_w_r] = (
img[mj_y : mj_y + mj_h_r, mj_x : mj_x + mj_w_r] * mj_not_alpha // 255
+ mj
)
# 注意要除255,不然溢出了就全白了