Overlay of two numpy arrays treating fourth plane as alpha level

I have two numpy arrays of the form (256, 256, 4). I would like to treat the fourth 256 x 256 plane as an alpha level and export the image in which these arrays were overlaid.

Sample code:

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)

      

This creates two images, fg:

test_fg.png

and bg:

test_bg:

I would like to be able to overlay fg to bg. That is, the final image should be gray in the upper left corner (because there is an alpha fg equal to 1), a mixture of gray and color noise in the lower right corner, and pure color noise in the other quandrants. I'm looking for something like add function that gives me a new np array.

Please note that I don't think this is the same as this answer , which uses matplotlib.pyplot.plt to overlay images and fiddles around with color maps. I don't think I will need to fiddle with color maps here, but maybe I am answering.

The reason I need a new np.array returned by the operation is because I want to do it iteratively with many images superimposed in order.

+3


source to share


1 answer


Alpha blending is usually done using the Porter and Duff equations:

enter image description here

where src and dst correspond to your background and background images, and the A and RGB pixel values ​​are floating point in the range [0, 1].

In your specific example:



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

      

Output:

enter image description here

+7


source







All Articles