opencv-python 指北

opencv-python 指北

社蕙 73 2023-03-20
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,不然溢出了就全白了

参考:使用OpenCV实现图像覆盖 - 腾讯云