簡體   English   中英

如何使用 PIL 將透明的 png 圖像與另一個圖像合並

[英]How to merge a transparent png image with another image using PIL

我有一個透明的 png 圖像foo.png並且我打開了另一個圖像:

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

現在我需要的是將foo.pngfoo2.png合並。

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

from PIL import Image

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

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

.paste()第一個參數是要粘貼的圖像。 第二個是坐標,秘方是第三個參數。 它表示將用於粘貼圖像的蒙版 如果您傳遞具有透明度的圖像,則 Alpha 通道將用作遮罩。

檢查 文檔

當背景圖像也包含透明度時, Image.paste無法按預期工作。 您需要使用真正的Alpha 合成

Pillow 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 通道,那么你可以使用常規的 paste 方法(應該更快)。

正如olt已經指出的那樣,當源目標都包含 alpha 時, Image.paste無法正常工作。

考慮以下場景:

兩個測試圖像,都包含 alpha:

在此處輸入圖片說明 在此處輸入圖片說明

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

使用Image.paste合成圖像, Image.paste所示:

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

生成以下圖像(覆蓋的紅色像素的 alpha 部分完全取自第二層。像素未正確混合):

在此處輸入圖片說明

使用Image.alpha_composite合成圖像, Image.alpha_composite所示:

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

產生以下(正確的)圖像:

在此處輸入圖片說明

還可以使用混合:

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

有一個類似的問題,很難找到答案。 以下函數允許您將具有透明度參數的圖像粘貼到另一個圖像上的特定偏移量。

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

我最終對用戶@P.Melch 提出的這條評論的建議進行了編碼,並由@Mithril 在我正在從事的一個項目中提出建議。

我也對越界安全進行了編碼,這是它的代碼 (我鏈接了一個特定的提交,因為這個存儲庫的未來可能會發生變化)

注意:我希望像np.array(Image.open(...))這樣的圖像中的 numpy 數組作為copy_from的輸入 A 和 B 以及此鏈接函數overlay參數。

依賴項是它之前的函數、 copy_from方法和 numpy 數組作為用於切片的 PIL Image 內容。

盡管該文件非常面向類,但如果您想使用該函數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方法,因為它特定於該項目。

很高興如果我幫助了你,一定要查看我正在談論的項目的 repo,這個問題和線程對我的開發幫助很大:)

關鍵代碼是:

_, _, _, alpha = image_element_copy.split()
image_bg_copy.paste(image_element_copy, box=(x0, y0, x1, y1), mask=alpha)

完整的功能是:

def paste_image(image_bg, image_element, cx, cy, w, h, rotate=0, h_flip=False):
    image_bg_copy = image_bg.copy()
    image_element_copy = image_element.copy()

    image_element_copy = image_element_copy.resize(size=(w, h))
    if h_flip:
        image_element_copy = image_element_copy.transpose(Image.FLIP_LEFT_RIGHT)
    image_element_copy = image_element_copy.rotate(rotate, expand=True)
    _, _, _, alpha = image_element_copy.split()
    # image_element_copy's width and height will change after rotation
    w = image_element_copy.width
    h = image_element_copy.height
    x0 = cx - w // 2
    y0 = cy - h // 2
    x1 = x0 + w
    y1 = y0 + h
    image_bg_copy.paste(image_element_copy, box=(x0, y0, x1, y1), mask=alpha)
    return image_bg_copy

上述功能支持:

  • 位置(cx,cy)
  • 自動將 image_element 調整為 (w, h)
  • 旋轉 image_element 而不裁剪它
  • 水平翻轉

這是我的代碼,用於合並 2 個不同大小的圖像,每個圖像都具有透明度和偏移量:

from PIL import Image

background = Image.open('image1.png')
foreground = Image.open("image2.png")

x = background.size[0]//2
y = background.size[1]//2

background = Image.alpha_composite(
    Image.new("RGBA", background.size),
    background.convert('RGBA')
)

background.paste(
    foreground,
    (x, y),
    foreground
)

background.show()

這個片段是先前答案的混合,在處理具有不同大小的圖像時將元素與偏移混合在一起,每個圖像都具有透明度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM