安装
pip install opencv-python
图像读取
三通道读取BGR
img_jpg = cv2.imread(path+"bg.jpg")
四通道读取BGRA
img_png = cv2.imread(path+"bg.png",cv2.IMREAD_UNCHANGED)
图像大小
# 输出: 高,宽,通道数
img_jpg.shape
# -> (1280, 720, 3)
img_png.shape
# -> (1280, 720, 4)
图像保存
# cv2.imwrite(filename, img)
cv2.imwrite("bg.jpg", img_jpg)
为三通道图像添加alpha通道, 设置为不透明
通道切分
b_channel, g_channel, r_channel = cv2.split(img_jpg)
b_channel, g_channel, r_channel, a_channel = cv2.split(img_png)
alpha通道生成
alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
通道合成
bg_alpha = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
图像缩放
cv2.resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)
# src: 图像
# dsize: 输出尺寸,当输入为0时,fx、fy皆不可为0,dsize = Size(round(fxsrc.cols),round(fysrc.rows))->(宽, 高)
# dst: 输出图,形态和输入图相同,当dsize不等于0,输出图尺寸会和dsize相同,当dsize等于0,输出图尺寸会由输入图尺寸、fx、fy计算而得
# fx: 水平缩放比例,当输入为0时,fx=(double)dsize.width/src.cols
# fy: 垂直缩放比例,当输入为0时,fy=(double)dsize.height/src.rows
# interpolation: 插值方法
interpolation插值方法
interpolation | 插值方法 | 备注 |
INTER_NEAREST | 最近邻插值 | |
INTER_LINEAR | 双线性插值(默认设置) | 放大时计算速度快, 且效果还可以 |
INTER_AREA | 使用像素区域关系进行重采样。 | 缩小时最佳 |
INTER_CUBIC | 4x4像素邻域的双三次插值 | 放大时效果最佳, 但计算速度慢 |
INTER_LANCZOS4 | 8x8像素邻域的Lanczos插值 |
反向变换公式
假设为源图,为目标图,指对应宽度,指对应高度,、为对应坐标值横纵坐标,则:
举个栗子:
假设源图大小是,目标图大小是,则有:
计算目标图坐标(1,2)所对应的源图坐标值为:
INTER_NEAREST最近邻插值
- 根据反向变换公式,计算出目标图坐标值所对应的源图坐标浮点值
- 对取整即可得到对应的源图坐标值,取整方法包括四舍五入、去尾法等。
INTER_LINEAR双线性插值
- 根据反向变换公式,计算出目标图坐标值所对应的源图坐标浮点值
- 令,其中、均为浮点坐标的整数部分,、为浮点坐标的小数部分,是取值[0,1)区间的浮点数
- 这个像素的值 可由原图像中坐标为 、、、所对应的周围四个像素的值决定:
INTER_AREA
使用像素区域关系进行重采样。它可能是图像抽取的首选方法,因为它会产生无云纹理的结果。但是当图像缩放时,它类似于INTER_NEAREST方法。
具体原理解释可参考OpenCV里的INTER_AREA究竟是在做啥?
图像融合
若两图像大小尺寸一致,可使用OpenCV中的addWeighted
方法进行图像融合:
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
参数说明
src1 – first input array.
alpha – weight of the first array elements.
src2 – second input array of the same size and channel number as src1.
beta – weight of the second array elements.
dst – output array that has the same size and number of channels as the input arrays.
gamma – scalar added to each sum.
dtype – optional depth of the output array; when both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth().
由参数说明可以看出,被叠加的两幅图像必须是尺寸相同、类型相同的。
融合效果
- 图A:
- 图B:
- 效果图:
局部融合
若两图像尺寸不一致,希望把图像A局部融合于图像bg(背景图)的某个区域,可根据图A的alpha通道数值计算透明度,将透明度作为权重weight进行加权融合:
此处采用向量化编程思想,代码如下:
import cv2
import os
import numpy as np
# 获取当前路径
path = os.getcwd() + "/"
# 读取背景图
bg = cv2.imread(path+"bg_air.jpg")
# 加上cv2.IMREAD_UNCHANGED保留png的alpha通道
plane = cv2.imread(path+"plane.png", cv2.IMREAD_UNCHANGED)
# 设置融合起始点坐标
x0 = 150
y0 = 500
# 构造与背景图同样大小的图A, 源图以外部分alpha通道数值为0, 表示全透明
b_channel, g_channel, r_channel = cv2.split(bg)
_channel = np.zeros(b_channel.shape, dtype=b_channel.dtype)
picA = cv2.merge((_channel, _channel, _channel, _channel))
height = plane.shape[0]
width = plane.shape[1]
picA[x0:height + x0, y0: width+y0] = plane[:, :]
# 若背景图为jpg, 则加上alpha通道, 数值为255, 表示不透明
alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
bg_alpha = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
# 对图片进行加权融合
_weight = picA[:, :, 3] / 255
weight = cv2.merge((_weight, _weight, _weight, _weight))
result = weight * picA + (1-weight) * bg_alpha
cv2.imwrite(path+"result.jpg", result)
融合效果
- 图A:
- 背景图:
- 融合效果