简体   繁体   中英

Image overlay certain pixels

I have two functions.
The first one changes the opacity of all black pixels in the overlay image to 0.
The second image overlays onto another one with changing opacity. But only for all pixels that are not black.
Overall I want to overlay images with different opacities and prevent that the black background does not show up.
It works just fine, but not really fast (both avg > 2sec). Is there a way to speed up the process a little? Numpy for example?
Here is what I have so far:

def remove_background(image):
   im = image.convert('RGBA')
   w, h = im.size
   for i in range(w):
       for j in range(h):
           cordinate = i, j
           rgb_map = im.getpixel(cordinate)
           if rgb_map == (0, 0, 0, 255):
               im.putpixel(cordinate, (0, 0, 0, 0))
   return im


def overlay_image(background, overlay, opacity=0.5):
   background = background.convert('RGBA')
   overlay = overlay.convert('RGBA')
   opacity = int(opacity * 255)
   w, h = background.size
   for i in range(w):
       for j in range(h):
           cordinate = i, j
           rgb_map = overlay.getpixel(cordinate)
           r = rgb_map[0]
           g = rgb_map[1]
           b = rgb_map[2]
           if r == 64 and g == 128 and b == 19:
               overlay.putpixel(cordinate, (64, 128, 19, opacity))
   background.paste(overlay, (0,0), overlay)
   return background

I know there is something from PIL called Image.blend() , but this is just for the whole image and not for certain pixels.

Here is an example I want to overlay:

animal

在此处输入图像描述

mask

在此处输入图像描述

result

在此处输入图像描述

Updated Answer

I think this is what your updated question is looking for:

#!/usr/bin/env python3

from PIL import Image

# Open the mask, discarding any alpha channel
mask = Image.open('mask.png').convert('RGB')

# Generate a new alpha channel that is transparent wherever the mask is black
alpha = mask.copy()
alpha = alpha.convert('L')
alpha.point(lambda p: 128 if p > 0 else 0)

# Open the animal, discarding its pointless alpha channel
animal = Image.open('animal.png').convert('RGB')

# Paste the mask over the animal, respecting transparency
animal.paste(mask,mask=alpha)
animal.save('result.png')

在此处输入图像描述

Alternative

As an alternative, you could simply add the mask to the animal. Where the mask is black (ie zero) it will add nothing:

#!/usr/bin/env python3

from PIL import Image, ImageChops

# Open the mask, discarding any alpha channel
mask = Image.open('mask.png').convert('RGB')

# Open the animal, discarding any alpha channel
animal = Image.open('animal.png').convert('RGB')

# Add the mask to the animal
res = ImageChops.add(animal, mask)
res.save('result.png')

在此处输入图像描述

You could scale the mask first, say by a half, using Image.point() with a lambda like below, if the green is too much.

Original Answer

Mmmm, if you want to mask an input image with another input image and show the results, I think you'd need three images, not two.

So, I am guessing this is what you want and it should be nice and fast:

#!/usr/bin/env python3

from PIL import Image

# Open the mask, discarding its pointless alpha channel and colour information
mask = Image.open('mask.png').convert('L')

# Generate a new alpha channel that is transparent wherever the mask is black
mask.point(lambda p: 255 if p > 0 else 0)

# Open the animal, discarding its pointless alpha channel
animal = Image.open('animal.png').convert('RGB')

# Put our lovely new alpha channel into animal image and save
animal.putalpha(mask)
animal.save('result.png')

mask.png

在此处输入图像描述

animal.png

在此处输入图像描述

在此处输入图像描述

Just for fun, here's another way of doing it leveraging Numpy:

#!/usr/bin/env python3

from PIL import Image
import numpy as np

# Open the overlay and animal,  discarding any alpha channel
overlay = Image.open('mask.png').convert('RGB')
animal  = Image.open('animal.png').convert('RGB')
mask    = overlay.convert('L')

# Make into Numpy arrays
overlay= np.array(overlay)
animal = np.array(animal)
mask   = np.array(mask)

# Blend animal and overlay
blended = animal//2 + overlay//2

# Choose blended or original at each location depending on mask
res = np.where(mask[...,np.newaxis], blended, animal)

# Revert to PIL Image and save
Image.fromarray(res).save('result.png')

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM