英文:
Transparent Background PIL Python
问题
我尝试将具有透明背景的图片粘贴到另一张图片上,使用PIL库。问题是我无法移除背景并将其无背景地粘贴到基础图片上。
我想要粘贴的图片有一个红色背景。我试图移除背景并像这样粘贴图片:
rm_image = Image.open("formations/testrm.png")
rm_copy = rm_image.copy().convert("RGBA")
background_color = (255, 0, 0, 255)
for x in range(rm_copy.width):
for y in range(rm_copy.height):
r, g, b, a = rm_copy.getpixel((x, y))
if (r, g, b, a) == background_color:
rm_copy.putpixel((x, y), (0, 0, 0, 0))
formation.paste(rm_copy, (1039, 396))
我还复制了基础图片并将其转换为RGBA,就像这样:
formation = Image.open(BytesIO(requests.get("LINK TO DISCORD ATTACHMENT").content))
formation = formation.copy().convert("RGBA")
在将基础图片转换为RGBA之前,粘贴的图像具有完全黑色背景。将基础图片转换为RGBA后,粘贴图像的背景变为深灰色。
如果有人能指出问题在哪里,并提出可能的修复方法,那将非常好。
用于重现的完整代码:
from io import BytesIO
import requests
from PIL import Image
formation = Image.open(BytesIO(requests.get("https://media.discordapp.net/attachments/1101171452377571428/1114864498424160316/FUSSBALL_4_3_3.png?width=1430&height=804").content))
formation = formation.copy().convert("RGBA")
rm_image = Image.open(BytesIO(requests.get("https://cdn.discordapp.com/attachments/1101171452377571428/1117737449716715570/testrm.png").content))
rm_copy = rm_image.copy().convert("RGBA")
background_color = (255, 0, 0, 255)
for x in range(rm_copy.width):
for y in range(rm_copy.height):
r, g, b, a = rm_copy.getpixel((x, y))
if (r, g, b, a) == background_color:
rm_copy.putpixel((x, y), (0, 0, 0, 0))
formation.paste(rm_copy, (1039, 396))
formation.show()
英文:
I'm trying to paste a picture with transparent background into a picture using PIL. The problem is that I'm unable to remove the background and paste it without background onto the base picture
The picture I want to paste has a red background. I'm trying to remove the backround and paste the picture like this:
rm_image = Image.open("formations/testrm.png")
rm_copy = rm_image.copy().convert("RGBA")
background_color = (255, 0, 0, 255)
for x in range(rm_copy.width):
for y in range(rm_copy.height):
r, g, b, a = rm_copy.getpixel((x, y))
if (r, g, b, a) == background_color:
rm_copy.putpixel((x, y), (0, 0, 0, 0))
formation.paste(rm_copy, (1039, 396))
I also copied the base image and converted it to rgba like this:
formation = Image.open(BytesIO(requests.get("LINK TO DISCORD ATTACHMENT").content))
formation = formation.copy().convert("RGBA")
before I converted the base picture to RGBA the pasted Image had a completely black background.
After converting the base picture to RGBA the background of the pasted Image is dark gray.
It would be really nice if someone could point out what is wrong and suggest possible ways to fix it.
Full code for recreation:
from io import BytesIO
import requests
from PIL import Image
formation = Image.open(BytesIO(requests.get("https://media.discordapp.net/attachments/1101171452377571428/1114864498424160316/FUSSBALL_4_3_3.png?width=1430&height=804").content))
formation = formation.copy().convert("RGBA")
rm_image = Image.open(BytesIO(requests.get("https://cdn.discordapp.com/attachments/1101171452377571428/1117737449716715570/testrm.png").content))
rm_copy = rm_image.copy().convert("RGBA")
background_color = (255, 0, 0, 255)
for x in range(rm_copy.width):
for y in range(rm_copy.height):
r, g, b, a = rm_copy.getpixel((x, y))
if (r, g, b, a) == background_color:
rm_copy.putpixel((x, y), (0, 0, 0, 0))
formation.paste(rm_copy, (1039, 396))
formation.show()
答案1
得分: 2
为了启用透明度,诀窍是将掩码作为参数传递给paste方法(与要复制的图像相同)。希望这正是您所寻找的!
from io import BytesIO
import requests
from PIL import Image
# 与以前一样加载并转换(但直接转换图像而不创建副本)
formation = Image.open(BytesIO(requests.get("https://media.discordapp.net/attachments/1101171452377571428/1114864498424160316/FUSSBALL_4_3_3.png?width=1430&height=804").content))
formation = formation.convert("RGBA")
rm_image = Image.open(BytesIO(requests.get("https://cdn.discordapp.com/attachments/1101171452377571428/1117737449716715570/testrm.png").content))
rm_image = rm_image.convert("RGBA")
# 创建带有透明背景的副本
rm_copy = Image.new('RGBA', rm_image.size, (0, 0, 0, 0))
for x in range(rm_image.width):
for y in range(rm_image.height):
r, g, b, a = rm_image.getpixel((x, y))
if r != 255 or g != 0 or b != 0: # 如果不是红色,则复制
rm_copy.putpixel((x, y), (r, g, b, a))
formation.paste(rm_copy, (1045, 400), rm_copy) # 稍微调整坐标以更好地重叠
formation.show()
英文:
To enable transparency the trick is to pass to the paste method a mask as parameter (that is the same as the image to copy).
Hoping is what you're looking for!
from io import BytesIO
import requests
from PIL import Image
#Load and convert as before (but convert directly the image without creating a copy)
formation = Image.open(BytesIO(requests.get("https://media.discordapp.net/attachments/1101171452377571428/1114864498424160316/FUSSBALL_4_3_3.png?width=1430&height=804").content))
formation = formation.convert("RGBA")
rm_image = Image.open(BytesIO(requests.get("https://cdn.discordapp.com/attachments/1101171452377571428/1117737449716715570/testrm.png").content))
rm_image = rm_image.convert("RGBA")
#Create the copy with transparent background
rm_copy = Image.new('RGBA', rm_image.size, (0, 0, 0, 0))
for x in range(rm_image.width):
for y in range(rm_image.height):
r, g, b, a = rm_image.getpixel((x, y))
if r != 255 or g != 0 or b != 0: #copy if it's not red
rm_copy.putpixel((x, y), (r, g, b, a))
formation.paste(rm_copy, (1045, 400), rm_copy) #slightly change the coordinates to overlap better
formation.show()
答案2
得分: 1
在Python中使用for
循环遍历图像是非常不建议的 - 它速度慢且容易出错。尝试使用内置的C编写的PIL函数或向量化的Numpy操作。
import numpy as np
from PIL import Image
# 打开两张输入图像
formation = Image.open('formation.png')
rm = Image.open('rm.png')
# 将"rm"转换为Numpy数组并找到所有不透明的红色像素
na = np.array(rm)
reds = np.all(na == [255, 0, 0, 255], axis=-1)
# 将reds转换回PIL图像以用作透明度蒙版
alpha = Image.fromarray(~reds)
# 使用alpha作为透明度蒙版将"rm"粘贴到"formation"上
formation.paste(rm, (1045, 400), alpha)
这比使用for
循环快了44倍,仅需250μs,而不是11.5ms。
英文:
Iterating over images with for
loops in Python is very inadvisable - it is slow and error-prone. Try to use built-in PIL functions written in C or vectorised Numpy operations.
import Numpy as np
from PIL import Image
# Open 2 input images
formation = Image.open('formation.png')
rm = Image.open('rm.png')
# Make "rm" into Numpy array and find all opaque red pixels
na = np.array(rm)
reds = np.all(na==[255,0,0,255], axis=-1)
# Convert reds back into PIL Image to use as alpha mask
alpha = Image.fromarray(~reds)
# Paste "rm" over "formation" with alpha as transparency mask
formation.paste(rm, (1045, 400), alpha)
This takes 250μs as opposed to 11.5ms using for
loops, so it is 44 times faster.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论