Як об'єднати прозоре PNG зображення з іншим зображенням за допомогою PIL


151

У мене прозоре png зображення "foo.png", і я відкрив інше зображення

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

Тепер мені потрібно злити foo.png з foo2.png.

(foo.png містить текст, і я хочу надрукувати цей текст на foo2.png)


71
Не використовуйте ;в кінці своїх команд у python: Це некрасиво ...
nosklo

6
Я буду мати це на увазі, дякую !!
Араккна

Відповіді:


288
import Image

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

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

Перший параметр .paste()- це зображення, яке потрібно вставити. Другі - координати, а секретний соус - третій параметр. Це вказує на маску яка буде використана для вставки зображення. Якщо ви передаєте зображення з прозорістю, альфа-канал використовується як маска.

Перевірте документи .


6
Щоб переконатися, що передній план містить прозорість у всіх випадках, використовуйте foreground.convert('RGBA')параметр маски.
Марк Рансом

2
Дякую. Я занадто пропустив третій параметр.
Сілуан Герін

13
Я отримуюValueError: bad transparency mask
Деніз Озгер

2
Таємний соус був смачним
AFP_555

3
@DenizOzger Щоб виправити ValueError: bad transparency maskвикористанняbg.paste(fg, (0, 0), fg.convert('RGBA'))
Mingwei Samuel

66

Image.pasteне працює, як очікувалося, коли фонове зображення також містить прозорість. Вам потрібно використовувати справжній Альфа-композит .

Подушка 2.0 містить alpha_compositeфункцію, яка це робить.

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

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

EDIT: Обидва зображення повинні бути типу RGBA. Тож вам потрібно зателефонувати, convert('RGBA')якщо вони палітруються тощо. Якщо фон не має альфа-каналу, тоді ви можете скористатися звичайним методом вставки (який повинен бути швидшим).


Я просто використав paste (), щоб накласти одне напівпрозоре зображення на інше, з PIL, і воно працювало так, як я очікував. Яким чином це не працює, як ви очікували?
Пітер Хансен

3
@PeterHansen, paste () не працює так, як очікувалося, "коли фонове зображення також містить прозорість".
homm

1
@PeterHansen Є приклад: github.com/python-pillow/Pillow/isissue/…
homm

@homm спасибі Це було так давно, що я не пам'ятаю ні про що спробував. Здається, я пропустив частину, яку ви цитували про фонове зображення, також маючи прозорість.
Пітер Хансен

4
Я отримую ValueError: image has wrong made, а @DenizOzger
digitaldavenyc

48

Як вже було зазначено, oltImage.paste не працює належним чином, коли обидва джерела та призначення містять альфа.

Розглянемо наступний сценарій:

Два тестових зображення, обидва містять альфа:

введіть тут опис зображення введіть тут опис зображення

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функцію?
Мітрил

3
Я думаю, вам доведеться створити нове порожнє зображення такого ж розміру, як і зображення гаргітки, наклеїти шар у потрібне положення та використовувати альфа-композицію для змішування нового зображення на цільове зображення.
P.Melch

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
Можливо, вони мають різні розміри. Можливо, вам знадобиться масштабувати або обрізати одну з них.
nvd

2
@ Schütze дивіться коментар nvd, тому що він / вона не пінг (використовуючи @blahblah) ви
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аргументи пов'язаної функції .

Залежності - це функція безпосередньо перед нею, copy_fromметод та масиви numpy як вміст зображення PIL для нарізки.

Хоча файл дуже орієнтований на клас, якщо ви хочете використовувати цю функцію overlay_transparent, не забудьте перейменуватиself.frame на масивний фоновий малюнок.

Або ви можете просто скопіювати весь файл (можливо, видалити деякий імпорт та 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накладений масив із накладеним та альфа-композицією, ви можете отримати з нього зображення PIL із overlayed = Image.fromarray(background.frame)чимось подібним:

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

Або просто background.save("save path")так, що береться безпосередньо з альфа-складеної внутрішньої self.frameзмінної.

Ви можете прочитати файл і знайти якісь - то інші функції добре з цією реалізацією I закодованої як і методи get_rgb_frame_array, resize_by_ratio, resize_to_resolution, rotate, gaussian_blur, transparency, vignetting:)

Ви, ймовірно, захочете видалити resolve_pending метод, який є специфічним для цього проекту.

Рада, якщо я допомогла вам, не забудьте перевірити репо проект проекту, про який я говорю, це питання і нитка мені дуже допомогли в розвитку :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.