实验1-2,用alpha混合,为图片替换一张新的背景

OpenCV学习记录(二)
实验说明
实验1-2:图像合成
实验要求:
1)现有一张4通道透明图像a.png:
2)从其中提取出alpha通道并显示;
3)用alpha混合,为a.png替换一张新的背景(bg.png)。
图像通道
首先,先了解什么是图像通道。
一幅完整的图像,红色绿色蓝色三个通道缺一不可。即使图像中看起来没有蓝色,只能说蓝色光的亮度均为0或者各像素值的红色和绿色通道不全为0,但不能说没有蓝色通道存在。
一张RGB图像含有三个通道:红(Red)、绿(Green)、蓝(Blue)。一张RGBA图像含有四个通道:红(Red)、绿(Green)、蓝(Blue)和Alpha(A)。一张灰度图则只有一个通道。
至于实验中提到的Alpha通道(α Channel),是计算机图形学中的术语,指的是特别的通道,意思是“非彩色”通道,主要是用来保存选区和编辑选区,代表透明度。至于为什么用α
来表示,可能是因为它是不表示某种颜色的图片的第一个属性,毕竟α自身没有所谓”透明度“的含义。
提取通道
那么,如何确定一张图片拥有的通道数,又怎样将不同通道的图像分别提取出来呢?
下面是提取通道的方式
1 | #OpenCV的方式 |
四通道图片
原图

r通道

g通道

b通道

α通道

图片合成
用alpha混合,为a.png替换一张新的背景(bg.png)
起初,筛选用关键字”图像合成“搜索到的教程,我选择用python的PIL库的Image.blend(im1,im2,0.5)
方法。
im1
和im2
是两张模式(mode,如rgb)、大小(size)和通道数都相同的图片,如果不同则需要预处理。第三个参数则是im1
的透明度,取值范围为[0,1]。
根据公式
blend_img = img1 * (1 – alpha) + img2 * alpha
调整alpha的值,产生的图片又不同的效果。
运行下面的代码,alpha是提取的alpha通道图,im2是背景图。
out=Image.blend(alpha,im2,0.5)
可是得到的结果却不是想象中的那样……

可以发现上图只是两张图片整体的简单重叠,中间的玩偶甚至只有轮廓。而把alpha
换成im1
,得到的效果是:

有一点雏形,调节参数也无济于事。但可以发现,blend函数应该并不是解决此问题的钥匙,alpha本应该是提取出的图像、矩阵,而非一个介于0到1的数字。
在opencv中的等效方法是cv.addWeighted(),也就是改变图像权重。

上图来自课件,介绍的是图像的加法和乘法,看上去不难理解,但是具体应该怎么操作呢?
搜索关键字,alpha blending
,算是找到了救星。
在这篇文章Alpha Blending using OpenCV (C++ / Python)中,作者较为详细的说明了alpha混合的相关知识(其实和我之前了解到的不差),并给出了实例代码,这才让我徒劳的搜索工作到了尽头。
1 | import cv2 |
对上面代码做出“本土化修改”,调节图片格式和通道(都转为3通道图像),最终得出了下面结果。
OHHHHHHHH!

代码解析
按照给定的代码运行的结果符合预期,下面分析一下这些代码具体做了什么(虽然本来就有注释)。
读入的三张图片预先做了处理使之格式一致,然后代码
foreground = foreground.astype(float)
将图像数据类型从unit8
转成了float
。
为什么要做这样的处理?
先看一段找到的Matlab的相关说明
为了节省存储空间,matlab为图像提供了特殊的数据类型uint8(8位无符号整数),以此方式存储的图像称作8位图像。matlab读入图像的数据是uint8,而matlab中数值一般采用double型(64位)运算。
运算的时候将原图像的灰度值转换成double的作用主要是考虑计算过程中的精度的问题,double的数据是有小数点的,而uint8是0-255的整数,如果直接用uint8计算,会在计算过程中产生舍入误差,这种误差在图像的数据中是比较大的误差。
python中同理。
python中展示图像时,图片数据类型应该是unit8,运算时,采用float或者np.double(将代码中的float替换为np.double效果一致)。
再看看两次乘法和一次加法操作的结果吧。
主体*Alpha
foreground = cv.multiply(alpha, foreground)

背景*(1-Alpha)
background = cv.multiply(1 - alpha, background)

主体+背景
outImage = cv.add(foreground, background)
就是前面的合成图片啦。
代码的逻辑,正应用了前面提过的公式
lmage Composite (合成):C=αF+(1-α)B
到此,实验一才算做完了。