Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alpha blending two images with OpenCV and/or Numpy [duplicate]

I would like to add a semi-transparent rectangle filled with a solid colour to an already loaded semi-transparent PNG. Here's an example input image I am using:

enter image description here

That image is loaded with a standard cv2.IMREAD_UNCHANGED flag so that alpha channel is perfectly preserved. That input image is stored in the image variable.

Here's my code that I have so far:

# get image dimensions
imgHeight, imgWidth = image.shape[:2]

# create empty overlay layer with 4 channels
overlay = np.zeros((imgHeight, imgWidth, 4), dtype = "uint8")

# draw semi-transparent red rectangle
overlay[200:300, 0:imgWidth] = (0, 0, 255, 200)

# extract alpha channel from overlay
alpha = cv2.split(overlay)[3]

# compute mask
mask = (np.multiply(alpha, 1.0 / 255))[:, :, np.newaxis]

# blend input image and overlay
output = cv2.convertScaleAbs(overlay * mask + image * (1 - mask))

And here's the result that I am getting:

enter image description here

At first glance it looks acceptable. We have our input image with a semi-transparent rectangle in the middle. However, upon closer inspection, we can observe strange behaviour when mixing alpha channels (marked with arrows):

enter image description here

It seems that alpha is not blended at all which results in original image pixels being only fully opaque or fully transparent.

Perhaps my method of blending transparent PNG with semi-transparent shapes is far from ideal. As a side note, I did try the cv2.addWeighted method but that yielded even worse results.

I would like the solution to be limited to OpenCV and/or Numpy. Any help would be greatly appreciated.

like image 405
Pono Avatar asked Nov 17 '20 11:11

Pono


People also ask

How do you blend images in OpenCV Python?

Like before, we start by importing the cv2 module, followed by reading both images and resizing them to be 400×400. We will then display the second image in a window called “blend“. It will be the one we will use every time we update the weights to display the resulting image.

How do you blend two images in python?

Syntax: PIL. Image. blend(image1, image2, alpha). image2: second image, must have the same mode and size as the first image.

What is alpha blending in image processing?

Alpha blending is the process of combining an image with a background to create the appearance of partial or full transparency. It is used to render multiple images into a single background image in separate passes and make one final image.


1 Answers

As unlut pointed out this is indeed a duplicate. Just in case someone stumbles on it, Mark Setchell's answer works pretty well:

# get image dimensions
imgHeight, imgWidth = image.shape[:2]

# create empty overlay layer with 4 channels
overlay = np.zeros((imgHeight, imgWidth, 4), dtype = "uint8")

# draw semi-transparent red rectangle
overlay[200:300, 0:imgWidth] = (0, 0, 255, 200)

# Extract the RGB channels
srcRGB = image[...,:3]
dstRGB = overlay[...,:3]

# Extract the alpha channels and normalise to range 0..1
srcA = image[...,3]/255.0
dstA = overlay[...,3]/255.0

# Work out resultant alpha channel
outA = srcA + dstA*(1-srcA)

# Work out resultant RGB
outRGB = (srcRGB*srcA[...,np.newaxis] + dstRGB*dstA[...,np.newaxis]*(1-srcA[...,np.newaxis])) / outA[...,np.newaxis]

# Merge RGB and alpha (scaled back up to 0..255) back into single image
outRGBA = np.dstack((outRGB,outA*255)).astype(np.uint8)

plt.imshow(outRGBA)
like image 58
Knight Forked Avatar answered Oct 19 '22 22:10

Knight Forked