图像覆盖某些像素
Image overlay certain pixels
我有两个功能。
第一个将叠加图像中所有黑色像素的不透明度更改为 0。
第二张图片叠加到另一张图片上,不透明度发生变化。但仅适用于所有非黑色像素。
总的来说,我想叠加不同不透明度的图像,防止黑色背景不显示。
它工作得很好,但不是很快(均 > 2 秒)。 有没有办法稍微加快这个过程? 例如 Numpy?
这是我目前所拥有的:
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
我知道 PIL
中有一个叫做 Image.blend()
的东西,但这只是针对整个图像而不是某些像素。
这是我要叠加的示例:
animal
mask
result
更新答案
我认为这就是您更新后的问题所寻找的:
#!/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')
备选
作为替代方案,您可以简单地将面具添加到动物身上。在掩码为黑色(即零)的地方,它不会添加任何内容:
#!/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')
如果绿色太多,您可以先使用 Image.point()
和如下所示的 lambda 缩放遮罩,比如缩小一半。
原答案
嗯,如果你想用另一个输入图像屏蔽一个输入图像并显示结果,我认为你需要三个图像,而不是两个。
所以,我猜这就是你想要的,它应该又好又快:
#!/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
只是为了好玩,这是利用 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')
我有两个功能。
第一个将叠加图像中所有黑色像素的不透明度更改为 0。
第二张图片叠加到另一张图片上,不透明度发生变化。但仅适用于所有非黑色像素。
总的来说,我想叠加不同不透明度的图像,防止黑色背景不显示。
它工作得很好,但不是很快(均 > 2 秒)。 有没有办法稍微加快这个过程? 例如 Numpy?
这是我目前所拥有的:
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
我知道 PIL
中有一个叫做 Image.blend()
的东西,但这只是针对整个图像而不是某些像素。
这是我要叠加的示例:
animal
mask
result
更新答案
我认为这就是您更新后的问题所寻找的:
#!/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')
备选
作为替代方案,您可以简单地将面具添加到动物身上。在掩码为黑色(即零)的地方,它不会添加任何内容:
#!/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')
如果绿色太多,您可以先使用 Image.point()
和如下所示的 lambda 缩放遮罩,比如缩小一半。
原答案
嗯,如果你想用另一个输入图像屏蔽一个输入图像并显示结果,我认为你需要三个图像,而不是两个。
所以,我猜这就是你想要的,它应该又好又快:
#!/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
只是为了好玩,这是利用 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')