将两个numpy数组叠加,第四维作为透明度层

5 投票
1 回答
4456 浏览
提问于 2025-04-18 16:23

我有两个形状为 (256, 256, 4) 的 numpy 数组。我想把这两个数组的第四个 256 x 256 的平面当作透明度(alpha),然后导出一张将这两个数组叠加后的图像。

代码示例:

import numpy as np
from skimage import io

fg = np.ndarray((256, 256, 4), dtype=np.uint8)
one_plane = np.random.standard_normal((256, 256)) * 100 + 128
fg[:,:,0:3] = np.tile(one_plane, 3).reshape((256, 256, 3), order='F')
fg[:, :, 3] = np.zeros((256, 256), dtype=np.uint8)
fg[0:128, 0:128, 3] = np.ones((128, 128), dtype=np.uint8) * 255
fg[128:256, 128:256, 3] = np.ones((128, 128), dtype=np.uint8) * 128

bg = np.ndarray((256, 256, 4), dtype=np.uint8)
bg[:,:,0:3] = np.random.standard_normal((256, 256, 3)) * 100 + 128
bg[:, :, 3] = np.ones((256, 256), dtype=np.uint8) * 255

io.imsave('test_fg.png', fg)
io.imsave('test_bg.png', bg)

这段代码生成了两张图像,前景图 fg:

test_fg.png

和背景图 bg:

test_bg

我想把 fg 叠加到 bg 上。也就是说,最终的图像左上角应该是灰色(因为那里 fg 的透明度是 1),右下角应该是灰色和颜色噪声的混合,而其他区域则是纯颜色噪声。我希望能有一个类似于加法的函数,给我一个新的 np 数组。

需要注意的是,我认为这和 这个回答 不一样,后者使用 matplotlib.pyplot.plt 来叠加图像,并且调整颜色映射。我觉得在这里不需要调整颜色映射,但也许答案是我确实需要。

我希望这个操作返回一个新的 np.array,因为我想对很多图像进行迭代叠加,按顺序叠加。

1 个回答

10

Alpha混合通常是通过Porter & Duff的公式来实现的:

enter image description here

在这个公式中,srcdst分别代表你想要叠加的前景图像和背景图像,而ARGB的像素值都是浮点数,范围在[0, 1]之间。

对于你具体的例子:

src_rgb = fg[..., :3].astype(np.float32) / 255.0
src_a = fg[..., 3].astype(np.float32) / 255.0
dst_rgb = bg[..., :3].astype(np.float32) / 255.0
dst_a = bg[..., 3].astype(np.float32) / 255.0

out_a = src_a + dst_a*(1.0-src_a)
out_rgb = (src_rgb*src_a[..., None]
           + dst_rgb*dst_a[..., None]*(1.0-src_a[..., None])) / out_a[..., None]

out = np.zeros_like(bg)
out[..., :3] = out_rgb * 255
out[..., 3] = out_a * 255

输出结果:

enter image description here

撰写回答