问题:如何使用PIL将透明png图像与另一个图像合并

我有一个透明的png图像“ foo.png”,并且用

im = Image.open("foo2.png");

现在我需要将foo.png与foo2.png合并。

(foo.png包含一些文本,我想在foo2.png上打印该文本)

I have a transparent png image “foo.png” and I’ve opened another image with

im = Image.open("foo2.png");

now what i need is to merge foo.png with foo2.png.

( foo.png contains some text and I want to print that text on foo2.png )


回答 0

import Image

background = Image.open("test1.png")
foreground = Image.open("test2.png")

background.paste(foreground, (0, 0), foreground)
background.show()

的第一个参数.paste()是要粘贴的图像。第二个是坐标,秘密调味料是第三个参数。它表示将用于粘贴图像的遮罩。如果通过透明图像,则Alpha通道将用作遮罩。

检查文档

import Image

background = Image.open("test1.png")
foreground = Image.open("test2.png")

background.paste(foreground, (0, 0), foreground)
background.show()

First parameter to .paste() is the image to paste. Second are coordinates, and the secret sauce is the third parameter. It indicates a mask that will be used to paste the image. If you pass a image with transparency, then the alpha channel is used as mask.

Check the docs.


回答 1

Image.paste当背景图像也包含透明度时,将无法正常工作。您需要使用真正的Alpha合成

枕头2.0包含alpha_composite执行此操作的功能。

background = Image.open("test1.png")
foreground = Image.open("test2.png")

Image.alpha_composite(background, foreground).save("test3.png")

编辑:两个图像都必须是RGBA类型。因此,convert('RGBA')如果它们带有调色板等,则需要调用。如果背景没有Alpha通道,则可以使用常规的粘贴方法(应该更快)。

Image.paste does not work as expected when the background image also contains transparency. You need to use real Alpha Compositing.

Pillow 2.0 contains an alpha_composite function that does this.

background = Image.open("test1.png")
foreground = Image.open("test2.png")

Image.alpha_composite(background, foreground).save("test3.png")

EDIT: Both images need to be of the type RGBA. So you need to call convert('RGBA') if they are paletted, etc.. If the background does not have an alpha channel, then you can use the regular paste method (which should be faster).


回答 2

正如olt已经指出的那样,Image.paste当源目标都包含alpha 时,将无法正常工作。

请考虑以下情形:

两个测试图像都包含alpha:

在此处输入图片说明 在此处输入图片说明

layer1 = Image.open("layer1.png")
layer2 = Image.open("layer2.png")

Image.paste像这样合成图像:

final1 = Image.new("RGBA", layer1.size)
final1.paste(layer1, (0,0), layer1)
final1.paste(layer2, (0,0), layer2)

产生以下图像(红色像素的叠加部分完全取自第二层。像素未正确混合):

在此处输入图片说明

Image.alpha_composite像这样合成图像:

final2 = Image.new("RGBA", layer1.size)
final2 = Image.alpha_composite(final2, layer1)
final2 = Image.alpha_composite(final2, layer2)

产生以下(正确)图像:

在此处输入图片说明

As olt already pointed out, Image.paste doesn’t work properly, when source and destination both contain alpha.

Consider the following scenario:

Two test images, both contain alpha:

enter image description here enter image description here

layer1 = Image.open("layer1.png")
layer2 = Image.open("layer2.png")

Compositing image using Image.paste like so:

final1 = Image.new("RGBA", layer1.size)
final1.paste(layer1, (0,0), layer1)
final1.paste(layer2, (0,0), layer2)

produces the following image (the alpha part of the overlayed red pixels is completely taken from the 2nd layer. The pixels are not blended correctly):

enter image description here

Compositing image using Image.alpha_composite like so:

final2 = Image.new("RGBA", layer1.size)
final2 = Image.alpha_composite(final2, layer1)
final2 = Image.alpha_composite(final2, layer2)

produces the following (correct) image:

enter image description here


回答 3

也可以使用混合:

im1 = Image.open("im1.png")
im2 = Image.open("im2.png")
blended = Image.blend(im1, im2, alpha=0.5)
blended.save("blended.png")

One can also use blending:

im1 = Image.open("im1.png")
im2 = Image.open("im2.png")
blended = Image.blend(im1, im2, alpha=0.5)
blended.save("blended.png")

回答 4

def trans_paste(bg_img,fg_img,box=(0,0)):
    fg_img_trans = Image.new("RGBA",bg_img.size)
    fg_img_trans.paste(fg_img,box,mask=fg_img)
    new_img = Image.alpha_composite(bg_img,fg_img_trans)
    return new_img
def trans_paste(bg_img,fg_img,box=(0,0)):
    fg_img_trans = Image.new("RGBA",bg_img.size)
    fg_img_trans.paste(fg_img,box,mask=fg_img)
    new_img = Image.alpha_composite(bg_img,fg_img_trans)
    return new_img

回答 5

有类似的问题,很难找到答案。通过以下功能,您可以将具有透明度参数的图像以特定的偏移量粘贴到另一幅图像上。

import Image

def trans_paste(fg_img,bg_img,alpha=1.0,box=(0,0)):
    fg_img_trans = Image.new("RGBA",fg_img.size)
    fg_img_trans = Image.blend(fg_img_trans,fg_img,alpha)
    bg_img.paste(fg_img_trans,box,fg_img_trans)
    return bg_img

bg_img = Image.open("bg.png")
fg_img = Image.open("fg.png")
p = trans_paste(fg_img,bg_img,.7,(250,100))
p.show()

Had a similar question and had difficulty finding an answer. The following function allows you to paste an image with a transparency parameter over another image at a specific offset.

import Image

def trans_paste(fg_img,bg_img,alpha=1.0,box=(0,0)):
    fg_img_trans = Image.new("RGBA",fg_img.size)
    fg_img_trans = Image.blend(fg_img_trans,fg_img,alpha)
    bg_img.paste(fg_img_trans,box,fg_img_trans)
    return bg_img

bg_img = Image.open("bg.png")
fg_img = Image.open("fg.png")
p = trans_paste(fg_img,bg_img,.7,(250,100))
p.show()

回答 6

我结束了自己的编码的建议此评论用户@ P.Melch一个项目我正在做,并建议通过@Mithril。

我也编码了安全性,这是它的代码。(我链接了一个特定的提交,因为在此存储库的将来情况可能会发生变化)

注意:我希望图像中有numpy数组,例如np.array(Image.open(...)),输入A和B copy_from以及此链接的函数overlay参数。

依赖项是位于其之前的函数,copy_from方法和numpy数组,它们是要切片的PIL图像内容。

尽管该文件是非常面向类的,但是如果要使用该函数overlay_transparent,请确保将重命名self.frame为背景图像numpy数组。

或者,您可以仅复制整个文件(可能删除一些导入和Utils类),然后与此Frame类进行交互,如下所示:

# Assuming you named the file frame.py in the same directory
from frame import Frame

background = Frame()
overlay = Frame()

background.load_from_path("your path here")
overlay.load_from_path("your path here")

background.overlay_transparent(overlay.frame, x=300, y=200)

然后,您将其background.frame作为叠加和alpha合成数组,可以使用overlayed = Image.fromarray(background.frame)或类似的东西从中获取PIL图像:

overlayed = Frame()
overlayed.load_from_array(background.frame)

或者就像background.save("save path")直接取自alpha复合内部self.frame变量一样。

您可以读取该文件,并找到其它的一些功能,这个实现我喜欢的编码方法get_rgb_frame_arrayresize_by_ratioresize_to_resolutionrotategaussian_blurtransparencyvignetting:)

您可能想要删除该resolve_pending项目专用的方法。

很高兴能为您提供帮助,请务必查看我正在谈论的项目的回购协议,该问题和线程对我的发展大有帮助:)

I ended up coding myself the suggestion of this comment made by the user @P.Melch and suggested by @Mithril on a project I’m working on.

I coded out of bounds safety as well, here’s the code for it. (I linked a specific commit because things can change in the future of this repository)

Note: I expect numpy arrays from the images like so np.array(Image.open(...)) as the inputs A and B from copy_from and this linked function overlay arguments.

The dependencies are the function right before it, the copy_from method, and numpy arrays as the PIL Image content for slicing.

Though the file is very class oriented, if you want to use that function overlay_transparent, be sure to rename the self.frame to your background image numpy array.

Or you can just copy the whole file (probably remove some imports and the Utils class) and interact with this Frame class like so:

# Assuming you named the file frame.py in the same directory
from frame import Frame

background = Frame()
overlay = Frame()

background.load_from_path("your path here")
overlay.load_from_path("your path here")

background.overlay_transparent(overlay.frame, x=300, y=200)

Then you have your background.frame as the overlayed and alpha composited array, you can get a PIL image from it with overlayed = Image.fromarray(background.frame) or something like:

overlayed = Frame()
overlayed.load_from_array(background.frame)

Or just background.save("save path") as that takes directly from the alpha composited internal self.frame variable.

You can read the file and find some other nice functions with this implementation I coded like the methods get_rgb_frame_array, resize_by_ratio, resize_to_resolution, rotate, gaussian_blur, transparency, vignetting :)

You’d probably want to remove the resolve_pending method as that is specific for that project.

Glad if I helped you, be sure to check out the repo of the project I’m talking about, this question and thread helped me a lot on the development :)


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。