Cara menggabungkan gambar png transparan dengan gambar lain menggunakan PIL

151

Saya memiliki gambar png transparan "foo.png" dan saya sudah membuka gambar lain dengan

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

sekarang yang saya butuhkan adalah menggabungkan foo.png dengan foo2.png.

(foo.png berisi beberapa teks dan saya ingin mencetak teks itu di foo2.png)

Arackna
sumber
71
Jangan gunakan ;di akhir perintah Anda dengan python: Ini jelek ...
nosklo
6
Aku akan mengingatnya di dalam pikiranku, terima kasih !!
Arackna

Jawaban:

288
import Image

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

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

Parameter pertama .paste()adalah gambar untuk di-paste. Kedua adalah koordinat, dan saus rahasia adalah parameter ketiga. Ini menunjukkan topeng yang akan digunakan untuk menempelkan gambar. Jika Anda melewatkan gambar dengan transparansi, maka saluran alfa digunakan sebagai mask.

Periksa dokumen .

nosklo
sumber
6
Untuk memastikan latar depan berisi transparansi dalam semua kasus, gunakan foreground.convert('RGBA')untuk parameter mask.
Mark Ransom
2
Terima kasih. Saya terlalu melewatkan parameter ketiga.
Silouane Gerin
13
Saya mendapatkanValueError: bad transparency mask
Deniz Ozger
2
Saus rahasia itu lezat
AFP_555
3
@DenizOzger Untuk memperbaiki ValueError: bad transparency maskpenggunaanbg.paste(fg, (0, 0), fg.convert('RGBA'))
Mingwei Samuel
66

Image.pastetidak berfungsi seperti yang diharapkan ketika gambar latar belakang juga mengandung transparansi. Anda harus menggunakan Pengomposisian Alfa asli .

Pillow 2.0 berisi alpha_compositefungsi yang melakukan ini.

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

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

EDIT: Kedua gambar harus dari jenis RGBA. Jadi, Anda perlu menelepon convert('RGBA')jika mereka palet, dll. Jika latar belakang tidak memiliki saluran alpha, maka Anda dapat menggunakan metode tempel biasa (yang harus lebih cepat).

olt
sumber
Saya hanya menggunakan paste () untuk overlay satu gambar semi-transparan pada yang lain, dengan PIL, dan itu berfungsi seperti yang saya harapkan. Dengan cara apa itu tidak berfungsi seperti yang Anda harapkan?
Peter Hansen
3
@PeterHansen, tempel () tidak berfungsi seperti yang diharapkan "ketika gambar latar belakang juga mengandung transparansi".
homm
1
@PeterHansen Ada contoh: github.com/python-pillow/Pillow/issues/…
homm
@ terima kasih. Itu sudah lama sekali saya tidak ingat apa yang saya coba. Sepertinya saya melewatkan bagian yang Anda kutip tentang gambar latar belakang juga memiliki transparansi.
Peter Hansen
4
Saya ValueError: image has wrong madejuga @DenizOzger
digitaldavenyc
48

Seperti yang sudah ditunjukkan olt , Image.pastetidak berfungsi dengan baik, ketika sumber dan tujuan keduanya mengandung alfa.

Pertimbangkan skenario berikut:

Dua gambar uji, keduanya mengandung alfa:

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

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

Mengomposit gambar menggunakan Image.pasteseperti:

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

menghasilkan gambar berikut (bagian alfa dari piksel merah overlay sepenuhnya diambil dari lapisan 2. Pixel tidak dicampur dengan benar):

masukkan deskripsi gambar di sini

Mengomposit gambar menggunakan Image.alpha_compositeseperti:

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

menghasilkan gambar (benar) berikut:

masukkan deskripsi gambar di sini

P.Melch
sumber
1
Terima kasih atas tangkapan layarnya! Sangat membantu!
Viet
1
Tapi alpha_compositetidak bisa mengatur offset, maukah Anda memberikan contoh untuk sepenuhnya menggantikan pastefungsi?
Mithril
3
Saya kira Anda harus membuat gambar kosong baru dengan ukuran yang sama dengan gambar garget, menempelkan layer pada posisi yang tepat dan menggunakan alpha_compositing untuk memadukan gambar baru di atas gambar target.
P.Melch
11

Satu juga dapat menggunakan blending:

im1 = Image.open("im1.png")
im2 = Image.open("im2.png")
blended = Image.blend(im1, im2, alpha=0.5)
blended.save("blended.png")
nvd
sumber
1
Yang satu ini bekerja untuk saya. Gambar harus memiliki ukuran yang persis sama, tetapi tidak apa-apa. Fungsi pasta tidak cukup memotongnya untuk saya ...
Liviu Sosu
2
'ValueError: gambar tidak cocok'
Schütze
2
Mungkin, mereka memiliki dimensi yang berbeda. Anda mungkin perlu mengukur atau memotong salah satunya.
nvd
2
@ Schütze lihat komentar nvd karena dia tidak ping (menggunakan @blahblah) Anda
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
陈旭 周 记
sumber
2
Hai, dapatkah Anda menambahkan sedikit lebih banyak konteks ke jawaban Anda? Kalau tidak, pemohon kemungkinan tidak akan mempelajari "mengapa" di belakangnya.
Jimm
0

Punya pertanyaan serupa dan kesulitan menemukan jawaban. Fungsi berikut memungkinkan Anda untuk menempelkan gambar dengan parameter transparansi di atas gambar lain pada offset tertentu.

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()
lee
sumber
ValueError: images do not match
lllllllllllll
0

Saya akhirnya coding sendiri saran dari komentar ini dibuat oleh pengguna @ P.Melch dan disarankan oleh @Mithril pada proyek yang sedang saya kerjakan.

Saya kode keluar dari batas keamanan juga, ini kode untuk itu . (Saya menautkan komit tertentu karena hal-hal dapat berubah di masa depan repositori ini)

Catatan: Saya berharap array numpy dari gambar seperti sehingga np.array(Image.open(...))input A dan B dari copy_fromdan overlayargumen fungsi terkait ini .

Ketergantungan adalah fungsi tepat sebelum itu, copy_frommetode, dan array numpy sebagai konten Gambar PIL untuk mengiris.

Meskipun file tersebut sangat berorientasi kelas, jika Anda ingin menggunakan fungsi itu overlay_transparent , pastikan untuk mengganti nama self.frameke array numpy gambar latar belakang Anda.

Atau Anda bisa menyalin seluruh file (mungkin menghapus beberapa impor dan Utilskelas) dan berinteraksi dengan kelas Bingkai ini seperti:

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

Kemudian, Anda memiliki background.framearray yang dikomposisikan secara overlay dan alfa, Anda bisa mendapatkan gambar PIL darinya dengan overlayed = Image.fromarray(background.frame)atau sesuatu seperti:

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

Atau sama background.save("save path")seperti yang mengambil langsung dari internal yang dikomposisikan alfaself.frame variabel .

Anda dapat membaca file dan menemukan beberapa fungsi lainnya baik dengan implementasi saya ini kode seperti metode get_rgb_frame_array, resize_by_ratio, resize_to_resolution, rotate, gaussian_blur, transparency,vignetting :)

Anda mungkin ingin menghapus resolve_pending metode karena itu spesifik untuk proyek itu.

Senang jika saya membantu Anda, pastikan untuk memeriksa repo proyek yang saya bicarakan, pertanyaan dan utas ini banyak membantu saya dalam pengembangan :)

Tremeschin
sumber