安装

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插值

反向变换公式

假设opencv mat设置通道数 opencv alpha通道_插值为源图,opencv mat设置通道数 opencv alpha通道_opencv_02为目标图,opencv mat设置通道数 opencv alpha通道_opencv mat设置通道数_03指对应宽度,opencv mat设置通道数 opencv alpha通道_缩放比例_04指对应高度,opencv mat设置通道数 opencv alpha通道_缩放比例_05opencv mat设置通道数 opencv alpha通道_插值_06为对应坐标值横纵坐标,则:
opencv mat设置通道数 opencv alpha通道_邻域_07

举个栗子:

假设源图大小是opencv mat设置通道数 opencv alpha通道_邻域_08,目标图大小是opencv mat设置通道数 opencv alpha通道_缩放比例_09,则有:

opencv mat设置通道数 opencv alpha通道_邻域_10
opencv mat设置通道数 opencv alpha通道_缩放比例_11

计算目标图坐标(1,2)所对应的源图坐标值为:
opencv mat设置通道数 opencv alpha通道_缩放比例_12
opencv mat设置通道数 opencv alpha通道_邻域_13

INTER_NEAREST最近邻插值
  1. 根据反向变换公式,计算出目标图坐标值opencv mat设置通道数 opencv alpha通道_缩放比例_14所对应的源图坐标浮点值opencv mat设置通道数 opencv alpha通道_缩放比例_15
  2. opencv mat设置通道数 opencv alpha通道_缩放比例_15取整即可得到对应的源图坐标值,取整方法包括四舍五入、去尾法等。
INTER_LINEAR双线性插值
  1. 根据反向变换公式,计算出目标图坐标值opencv mat设置通道数 opencv alpha通道_缩放比例_14所对应的源图坐标浮点值opencv mat设置通道数 opencv alpha通道_缩放比例_15
  2. opencv mat设置通道数 opencv alpha通道_opencv mat设置通道数_19,其中opencv mat设置通道数 opencv alpha通道_opencv mat设置通道数_20opencv mat设置通道数 opencv alpha通道_缩放比例_21均为浮点坐标的整数部分,opencv mat设置通道数 opencv alpha通道_缩放比例_22opencv mat设置通道数 opencv alpha通道_opencv_23为浮点坐标的小数部分,是取值[0,1)区间的浮点数
  3. 这个像素的值opencv mat设置通道数 opencv alpha通道_邻域_24 可由原图像中坐标为 opencv mat设置通道数 opencv alpha通道_opencv_25opencv mat设置通道数 opencv alpha通道_插值_26opencv mat设置通道数 opencv alpha通道_opencv mat设置通道数_27opencv mat设置通道数 opencv alpha通道_邻域_28所对应的周围四个像素的值决定:
    opencv mat设置通道数 opencv alpha通道_opencv_29
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().

opencv mat设置通道数 opencv alpha通道_缩放比例_30

由参数说明可以看出,被叠加的两幅图像必须是尺寸相同、类型相同的。

融合效果

  • 图A:

opencv mat设置通道数 opencv alpha通道_opencv mat设置通道数_31

  • 图B:

opencv mat设置通道数 opencv alpha通道_插值_32

  • 效果图:

opencv mat设置通道数 opencv alpha通道_邻域_33

局部融合

若两图像尺寸不一致,希望把图像A局部融合于图像bg(背景图)的某个区域,可根据图A的alpha通道数值计算透明度,将透明度作为权重weight进行加权融合:

opencv mat设置通道数 opencv alpha通道_opencv_34
opencv mat设置通道数 opencv alpha通道_缩放比例_35

此处采用向量化编程思想,代码如下:

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:

opencv mat设置通道数 opencv alpha通道_缩放比例_36

  • 背景图:

opencv mat设置通道数 opencv alpha通道_缩放比例_37

  • 融合效果

opencv mat设置通道数 opencv alpha通道_缩放比例_38