PILを使用して透明なPNG画像を別の画像とマージする方法


151

私は透明なpng画像「foo.png」を持っていて、別の画像を

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

ここで必要なのは、foo.pngをfoo2.pngとマージすることです。

(foo.pngにはテキストが含まれており、そのテキストをfoo2.pngに印刷したい)


71
;Pythonでコマンドの最後に使用しないでください:醜い...
nosklo

6
心に留めておきます、ありがとう!!
Arackna

回答:


288
import Image

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

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

最初のパラメータ.paste()は、貼り付ける画像です。2番目は座標で、秘密のソースは3番目のパラメーターです。画像の貼り付けに使用されるマスクを示します。透明度のある画像を渡すと、アルファチャネルがマスクとして使用されます。

ドキュメントを確認してください。


6
すべてのケースで前景に透明度が含まれるようにするにforeground.convert('RGBA')は、マスクパラメータに使用します。
Mark Ransom 2012年

2
ありがとう。3番目のパラメーターが不足していました。
Silouane Gerin 2013

13
取得中ValueError: bad transparency mask
Deniz Ozger

2
秘密のソースは美味しかった
AFP_555

3
@DenizOzger ValueError: bad transparency mask使用を修正するにはbg.paste(fg, (0, 0), fg.convert('RGBA'))
Mingwei Samuel

66

Image.paste背景画像にも透明度が含まれていると、期待どおりに動作しません。実際のアルファ合成を使用する必要があります。

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')、それらがパレット化されているかどうかなどを呼び出す必要があります。背景にアルファチャネルがない場合は、通常の貼り付け方法を使用できます(これは高速です)。


PILを使用して、paste()を使用して、ある半透明のイメージを別の半透明のイメージにオーバーレイしましたが、期待どおりに機能しました。どのようにして期待どおりに機能しませんか?
Peter Hansen

3
@ PeterHansen、paste()が「背景画像にも透明度が含まれている場合」期待どおりに機能しません。
2014年

1
:@PeterHansen例があるgithub.com/python-pillow/Pillow/issues/...
homm

@ホムありがとう。それはずっと前のことでした。背景画像についても透明性があるとおっしゃっていた部分を見逃していたようです。
Peter Hansen、

4
私が手ValueError: image has wrong madeにも@DenizOzger
digitaldavenyc

48

OLTすでに指摘し、Image.paste正常に動作しない、ときに、ソース宛先の両方のアルファが含まれています。

次のシナリオを検討してください。

2つのテスト画像、どちらもアルファを含む:

ここに画像の説明を入力してください ここに画像の説明を入力してください

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)

次の画像を生成します(オーバーレイされた赤いピクセルのアルファ部分は、第2レイヤーから完全に取得されます。ピクセルは正しくブレンドされていません)。

ここに画像の説明を入力してください

Image.alpha_composite同様に使用して画像を合成する:

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

次の(正しい)画像が生成されます。

ここに画像の説明を入力してください


1
スクリーンショットをありがとう!本当に役立ちます!
ベトナム

1
しかしalpha_composite、オフセットを設定できませんpaste。関数を完全に置き換える例を挙げていただけませんか?
ミスリル2017

3
garget画像と同じサイズの新しい空の画像を作成し、適切な位置にレイヤーを貼り付け、alpha_compositingを使用してターゲット画像の上に新しい画像をブレンドする必要があると思います。
P.Melch 2017

11

ブレンドを使用することもできます:

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

1
これは私のために無理なく働いた。画像は正確に同じサイズでなければなりませんが、問題ありません。貼り付け機能は私のためにそれを完全にカットしませんでした...
Liviu Sosu

2
「とValueError:イメージが一致していない」
Schütze

2
おそらく、それらは異なる次元のものです。それらの1つをスケーリングまたはトリミングする必要がある場合があります。
nvd '20

2
@Schützeは(@blahblahを使用して)pingを送信しなかったため、nvdのコメントを参照してください
MilkyWay90

1
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

2
こんにちは、あなたの答えにもう少しコンテキストを追加できますか?それ以外の場合、リクエスタはその背後にある「理由」を知る可能性が低くなります。
jimf

0

同様の質問があり、答えを見つけるのが困難でした。次の関数を使用すると、特定のオフセットで別の画像の上に透明度パラメーターを使用して画像を貼り付けることができます。

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

ValueError: images do not match
lllllllllllll

0

結局、ユーザー@ P.Melchによるこのコメントの提案と、自分が取り組んでいるプロジェクトに関する@Mithril の提案を自分でコーディングすることになりました。

私も範囲外の安全性をコーディングしました、これはそのためのコードです。(このリポジトリの将来は状況が変わる可能性があるため、特定のコミットをリンクしました)

注:np.array(Image.open(...))入力からの入力AとB、copy_fromおよびこのリンクされた関数のoverlay引数と同様に、画像からのnumpy配列を期待しています。

依存関係は、その直前の関数、copy_fromメソッド、およびスライス用のPILイメージコンテンツとしてのnumpy配列です。

ファイルは非常にクラス指向ですが、その関数を使用する場合は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、オーバーレイされたアルファ合成配列として、overlayed = Image.fromarray(background.frame)次のようなものでPIL画像を取得できます。

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

またはbackground.save("save path")、アルファ合成された内部self.frame変数から直接取得します。

あなたはファイルを読み込み、メソッドのようにコード化されたこの実装Iと他のいくつかの素敵な機能を見つけることができますget_rgb_frame_arrayresize_by_ratioresize_to_resolutionrotategaussian_blurtransparencyvignetting:)

resolve_pendingそれはそのプロジェクトに固有であるため、おそらくメソッドを削除する必要があります。

私があなたを助けてくれてうれしいです、私が話しているプロジェクトのレポを必ずチェックしてください、この質問とスレッドは開発でたくさん助けてくれました:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.