Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PIL remove background image from image

With a background image, would I be able to remove that background from another image and get all of the discrepancies? For example:

enter image description here

enter image description here

Pretend I have these two images saved. How could I remove the first picture from the second picture while keeping all of the cats?

like image 767
Spooky Avatar asked Feb 21 '16 03:02

Spooky


People also ask

How can I remove a background from a picture?

Select the picture that you want to remove the background from. On the toolbar, select Picture Format > Remove Background, or Format > Remove Background.


1 Answers

According to the PIL handbook, the ImageChops module has a subtract operation:

ImageChops.subtract(image1, image2, scale, offset) => image
Subtracts two images, dividing the result by scale and adding the offset.
If omitted, scale defaults to 1.0, and offset to 0.0.
out = (image1 - image2) / scale + offset

You can use the resulting image as a mask for the image with the cats: Keep the pixels where the mask is non-zero, otherwise make them the desired background colour.

Sample code below:

from PIL import Image
from PIL import ImageChops
image1 = Image.open("image1.jpg") # no cats
image2 = Image.open("image2.jpg") # with cats

image = ImageChops.subtract(image2, image1)

mask1 = Image.eval(image, lambda a: 0 if a <= 24 else 255)
mask2 = mask1.convert('1')

blank = Image.eval(image, lambda a: 0)

new = Image.composite(image2, blank, mask2) 
new.show()

It almost works :-)

resulting image

There is a bit more difference between the two images than it seems. Because the images are stored as JPGs, they are lossy. They will be rendered slightly differently, so the subtract operation will not always result in zero (i.e. black) for the pixels in the areas that are the same.

For this reason, I had to use lambda a: 0 if a <= 24 else 255 for the eval function to get a reasonable result.

If you use loss-less images it should work properly. You should then use 0 if a == 0 else 255 to create the mask.

Note that if some 'cat' pixels accidentally are the same as the background pixel, they will show up as black pixels.

like image 61
NZD Avatar answered Nov 15 '22 08:11

NZD