Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I overlay one image over another so that dark background is transparent?

I have 2 images, test1.jpg and test2.jpg that are RGB images. They have been converted from a 2D numpy array so they are monochrome images. They have the same shape. When I use the paste function, I only see one of the images instead of both.

Here are the test1 and test2 jpgs:

test1

test2.

This is what I get after doing test1.paste(test2) and test1.save('final.jpg'):

result of paste

Why is it only showing test2?

Here is my code:

im1 = Image.open('test1.jpg')
im2 = Image.open('test2.jpg')
im1.paste(im2)
im1.save('final.jpg')
like image 918
Harsh Ambardekar Avatar asked Sep 20 '25 12:09

Harsh Ambardekar


2 Answers

You simply need to choose the lighter of your two images at each point with PIL Channel Operations:

from PIL import Image, ImageChops

im1 = Image.open('test1.jpeg')
im2 = Image.open('test2.jpeg')

# Choose lighter of the two images at each pixel location
combined = ImageChops.lighter(im1,im2)

enter image description here


Note that you could use paste() as you originally intended, but that it will paste all the black as well as the white pixels from image2 over image1. In order to avoid that, you would need to make a mask and only paste where image2 is non-zero. That might look like this:

im1 = Image.open('test1.jpeg')
im2 = Image.open('test2.jpeg')

# Make greyscale mask from image2
mask = im2.convert('L')
mask = mask.point(lambda i: 255 if i>0 else 0)

# Paste image2 into image1 only where image2 has non-black content
im1.paste(im2, mask=mask)

I just think the ImageChops.lighter() method is simpler.


Note that these two methods will give subtly different results. For example, if a pixel is 192 in image1 and 67 in image2, the ImageChops.lighter() method will result in 192, whereas the paste() method will see there is something in image2, and therefore give you the 67. Your choice!

like image 97
Mark Setchell Avatar answered Sep 23 '25 04:09

Mark Setchell


paste is the wrong tool for this job, because it completely replaces the original image with the image you're pasting. It appears you wanted something closer to the blend function which produces a mix of both images. Unfortunately this has the side effect of darkening the image, because white blended with black becomes a middle gray; you'll probably want to double the values to compensate.

final = Image.blend(test1, test2, 0.5)
final = Image.eval(final, lambda x: 2*x))
like image 32
Mark Ransom Avatar answered Sep 23 '25 03:09

Mark Ransom