Python PIL-функция для разделения смешивания двух изображений?

EDIT: код работает сейчас, благодаря Марку и зефиру. zephyr также имеет два альтернативных рабочих решения ниже.

Я хочу разделить смесь двух изображений с PIL. Я нашел ImageChops.multiply(image1, image2) но я не мог найти подобное

3 ответов


здесь есть математическое определение функции деления: http://www.linuxtopia.org/online_books/graphics_tools/gimp_advanced_guide/gimp_guide_node55_002.html

вот реализация с scipy / matplotlib:

import numpy as np
import scipy.misc as mpl

a = mpl.imread('01background.jpg')
b = mpl.imread('02testgray.jpg')

c = a/((b.astype('float')+1)/256)
d = c*(c < 255)+255*np.ones(np.shape(c))*(c > 255)

e = d.astype('uint8')

mpl.imshow(e)
mpl.imsave('output.png', e)

Если вы не хотите использовать matplotlib, вы можете сделать это так (я предполагаю, что у вас есть numpy):

imgA = Image.open('01background.jpg')
imgA.load()
imgB = Image.open('02testgray.jpg')
imgB.load()

a = asarray(imgA)
b = asarray(imgB)
c = a/((b.astype('float')+1)/256)
d = c*(c &lt 255)+255*ones(shape(c))*(c &gt 255)
e = d.astype('uint8')

imgOut = Image.fromarray(e)
imgOut.save('PILdiv0.png', 'PNG')


проблема у вас есть, когда у вас есть ноль в изображении B-это вызывает деление на ноль. Если вы конвертируете все эти значения в один, я думаю, вы получите желаемый результат. Это устранит необходимость проверять нули и фиксировать их в результате.


ты спрашиваешь:

есть ли более эффективный способ сделать эту операцию разделения смеси (меньше шагов и быстрее)?

вы также можете использовать пакет python режимы наложения. Он написан с векторизованной математикой Numpy и, как правило, быстро. Установите его через pip install blend_modes. Я написал команды более подробным образом, чтобы улучшить читаемость,было бы короче их связывать. Использовать blend_modes как это разделить изображения:

from PIL import Image
import numpy
import os
from blend_modes import blend_modes

# Load images
imgA = Image.open('01background.jpg')
imgA = numpy.array(imgA)
# append alpha channel
imgA = numpy.dstack((imgA, numpy.ones((imgA.shape[0], imgA.shape[1], 1))*255))
imgA = imgA.astype(float)

imgB = Image.open('02testgray.jpg')
imgB = numpy.array(imgB)
# append alpha channel
imgB = numpy.dstack((imgB, numpy.ones((imgB.shape[0], imgB.shape[1], 1))*255))
imgB = imgB.astype(float)

# Divide images
imgOut = blend_modes.divide(imgA, imgB, 1.0)

# Save images
imgOut = numpy.uint8(imgOut)
imgOut = Image.fromarray(imgOut)
imgOut.save('PILdiv0.png', 'PNG')

os.system('start PILdiv0.png')

имейте в виду, что для этого оба изображения должны иметь одинаковые размеры, например imgA.shape == (240,320,3) и imgB.shape == (240,320,3).