Reputation: 11836
Say I have an BGRA image as numpy
array that looks pretty much like this:
[[[233 228 230 128]
[233 228 230 128]
[233 228 230 0]
...
[164 160 159 65]
[199 197 196 65]
[255 255 254 120]]
That looks pretty straightforward - three colour channels + one alpha that controls transparency of pixels. Saving that numpy array in a PNG format results in an image that is semi-transparent as it should be.
However, when saving it as JPEG, the alpha channel is dropped completely and the all of the pixels are fully opaque.
As JPEG does not support alpha-transparency, I would like my semi-transparent image (the numpy array above) to be saved on a white background instead. That way, it would appear as if the pixels would still be semi-transparent.
How can I overlay the semi-transparent numpy array on a fully white background? I am using mainly numpy and OpenCV.
Upvotes: 3
Views: 1202
Reputation: 208052
I think you are looking more for gradated alpha-blending than the simpler alpha-thresholding that Fred's answer nicely demonstrates.
I made a sample image with an alpha gradient in the middle for test purposes. Here it is as a normal image and composited over a checkerboard to show the transparency like Photoshop does:
To do alpha blending you use the formula:
result = alpha * Foreground + (1-alpha)*Background
where the values are all floats scaled on the range 0..1
The code for blending over black and then white background follows:
#!/usr/bin/env python3
import cv2
import numpy as np
# Load image, including gradient alpha layer
im = cv2.imread('GradientAlpha.png', cv2.IMREAD_UNCHANGED)
# Separate BGR channels from A, make everything float in range 0..1
BGR = im[...,0:3].astype(np.float)/255
A = im[...,3].astype(np.float)/255
# First, composite image over black background using:
# result = alpha * Foreground + (1-alpha)*Background
bg = np.zeros_like(BGR).astype(np.float) # black background
fg = A[...,np.newaxis]*BGR # new alpha-scaled foreground
bg = (1-A[...,np.newaxis])*bg # new alpha-scaled background
res = cv2.add(fg, bg) # sum of the parts
res = (res*255).astype(np.uint8) # scaled back up
cv2.imwrite('OverBlack.png', res)
# Now, composite image over white background
bg = np.zeros_like(BGR).astype(np.float)+1 # white background
fg = A[...,np.newaxis]*BGR # new alpha-scaled foreground
bg = (1-A[...,np.newaxis])*bg # new alpha-scaled background
res = cv2.add(fg, bg) # sum of the parts
res = (res*255).astype(np.uint8) # scaled back up
cv2.imwrite('OverWhite.png', res)
That gives this over black:
And this over white:
Keywords: Image processing, Python, OpenCV, alpha, alpha blending, alpha compositing, overlay.
Upvotes: 4
Reputation: 53202
In Python OpenCV Numpy, you can separate the alpha channel from the image. So if imgA is the image with alpha channel. Then separate the rgb image (img) and the alpha channel (alpha)
img = imgA[:,:,0:3]
alpha = imgA[:,:,3]
Then set the color of img to white where the alpha is black
img[alpha == 0] = (255,255,255)
Upvotes: 1