透明背景 PIL Python

huangapple go评论140阅读模式
英文:

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()

透明背景 PIL Python

英文:

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()

透明背景 PIL Python

答案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。

透明背景 PIL Python

英文:

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)

透明背景 PIL Python

This takes 250μs as opposed to 11.5ms using for loops, so it is 44 times faster.

huangapple
  • 本文由 发表于 2023年6月12日 16:29:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76454814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定