NumPy, PIL добавление изображения

Я пытаюсь добавить два изображения вместе, используя NumPy и PIL. Я бы сделал это в MATLAB примерно так:

>> M1 = imread('_1.jpg');
>> M2 = imread('_2.jpg');
>> resM = M1 + M2;
>> imwrite(resM, 'res.jpg');

Я получаю что-то вроде этого:

http://www.deadlink.cc/matlab.jpg

Используя программу компоновки и добавляя изображения, результат MATLAB кажется правильным.

В Python я пытаюсь сделать то же самое:

from PIL import Image
from numpy import *

im1 = Image.open('/Users/rem7/Desktop/_1.jpg')
im2 = Image.open('/Users/rem7/Desktop/_2.jpg')

im1arr = asarray(im1)
im2arr = asarray(im2)

addition = im1arr + im2arr

resultImage = Image.fromarray(addition)
resultImage.save('/Users/rem7/Desktop/a.jpg')

и я получаю что-то вроде этого:

http://www.deadlink.cc/python.jpg

Почему я получаю все эти причудливые цвета? Я также пытался использовать ImageMath.eval("a+b", a=im1, b=im2), но получаю сообщение об ошибке RGB не поддерживается.

Я также видел, что есть Image.blend(), но для этого требуется альфа.

Каков наилучший способ достичь того, что я ищу?

Исходные изображения (изображения удалены):

http://www.deadlink.cc/_1.jpg http://www.deadlink.cc/_2.jpg

Хм, хорошо, я добавил исходные изображения с помощью значка добавления изображения, и они отображаются, когда я редактирую сообщение, но по какой-то причине изображения не отображаются в сообщении.

(изображения были удалены) 2013 05 09


person rem7    schedule 08.02.2009    source источник


Ответы (5)


Как все уже говорили, странные цвета, которые вы наблюдаете, переполняются. И, как вы указываете в комментарии к ответу Шнаадера, вы все еще будет переполнение, если вы добавите свои изображения следующим образом:

addition=(im1arr+im2arr)/2

Причиной этого переполнения является то, что ваши массивы NumPy (im1arr im2arr) имеют тип uint8 (т. е. 8-битные). Это означает, что каждый элемент массива может содержать только значения до 255, поэтому, когда ваша сумма превышает 255, она возвращается к 0:

>>>array([255,10,100],dtype='uint8') +  array([1,10,160],dtype='uint8')
array([ 0, 20,  4], dtype=uint8)

Чтобы избежать переполнения, ваши массивы должны содержать значения за пределами 255. Вам нужно, например, преобразовать их в числа с плавающей запятой, выполнить операцию смешивания и преобразовать результат обратно в uint8. :

im1arrF = im1arr.astype('float')
im2arrF = im2arr.astype('float')
additionF = (im1arrF+im2arrF)/2
addition = additionF.astype('uint8')

Вы не должны делать следующее:

addition = im1arr/2 + im2arr/2

когда вы теряете информацию, сжимая динамику изображения (вы фактически делаете изображения 7-битными) перед выполнением смешивания информации.

Примечание MATLAB: причина, по которой вы не видите этой проблемы в MATLAB, вероятно, заключается в том, что MATLAB неявно заботится о переполнении в одной из своих функций.

person Ivan    schedule 08.02.2009
comment
Почему «плавать»? uint16 будет достаточно. - person jfs; 11.02.2009
comment
Не было рациональной причины для выбора float, uint16 действительно было бы достаточно. - person Ivan; 11.02.2009

Использование функции blend() PIL со значением альфа 0,5 будет эквивалентно (im1arr + im2arr)/2. Blend не требует, чтобы изображения имели альфа-слои.

Попробуй это:

from PIL import Image
im1 = Image.open('/Users/rem7/Desktop/_1.jpg')
im2 = Image.open('/Users/rem7/Desktop/_2.jpg')
Image.blend(im1,im2,0.5).save('/Users/rem7/Desktop/a.jpg')
person Paul    schedule 08.02.2009
comment
это особенно удобно для выполнения работы без перетаскивания numpy. - person DarenW; 12.05.2009

Чтобы зафиксировать значения массива numpy:

>>> c = a + b
>>> c[c > 256] = 256
person jfs    schedule 08.02.2009
comment
Предполагается, что тип элементов больше, чем uint8. - person jfs; 11.02.2009

Кажется, код, который вы разместили, просто суммирует значения, а значения больше 256 переполняются. Вам нужно что-то вроде «(a + b)/2» или «min (a + b, 256)». Последнее похоже на то, как это делает ваш пример Matlab.

person schnaader    schedule 08.02.2009
comment
Да, Matlab фиксирует значения при выполнении арифметических операций со значениями uint8 (например, он неявно выполняет эквивалент max(double(a)+double(b),256)) - person Mr Fooz; 08.02.2009
comment
Когда я пытаюсь сделать max(im1arr+im2arr,256), я получаю сообщение об ошибке: ValueError: Значение истинности массива с более чем одним элементом неоднозначно. Используйте a.any() или a.all() Я делаю (im1arr+im2arr)/2 Я получаю необычные цвета, только тусклее, максимальное значение 127, поэтому я сделал: add=(im1arr/2)+(im2arr/2) и это, кажется, работает. - person rem7; 08.02.2009
comment
Разве вы на самом деле не хотите min(a + b, 256), потому что, если вы получите значение более 256, вы хотите зафиксировать значение на 256 (вы не хотите принимать значение более 256). В любом случае, чтобы исправить ошибку, указанную @rem7, вы можете сделать additionF = np.minimum(im1arrF + im2arrF, 256) - person Vincent; 29.06.2016

Ваши образцы изображений не отображаются у меня, поэтому я собираюсь немного угадать.

Я не могу точно вспомнить, как работает преобразование numpy в pil, но есть два вероятных случая. Я на 95% уверен, что это 1, но ставлю 2 на случай, если я ошибаюсь. 1) 1 im1Arr представляет собой массив MxN целых чисел (ARGB), и когда вы складываете im1arr и im2arr вместе, вы переполняетесь из одного канала в другой, если компоненты b1+b2>255. Я предполагаю, что Matlab представляет свои изображения в виде массивов MxNx3, поэтому каждый цветовой канал является отдельным. Вы можете решить эту проблему, разделив каналы изображений PIL, а затем создав массивы numpy.

2) 1 im1Arr представляет собой массив байтов MxNx3, и когда вы складываете вместе im1arr и im2arr, вы оборачиваете компонент.

Вам также придется изменить масштаб диапазона до 0-255 перед отображением. Ваш выбор: разделить на 2, масштабировать на 255/array.max() или сделать клип. Я не знаю, что делает матлаб

person hacken    schedule 08.02.2009
comment
Изображения по-прежнему не отображаются? Я отредактировал вопрос, и после этого он работает здесь. - person schnaader; 08.02.2009
comment
работает для меня сейчас. Это определенно похоже на проблему обертывания/насыщенности. Также было бы неплохо, если бы вы разместили свои исходные изображения. - person hacken; 08.02.2009
comment
Я думаю, что преобразование pil делает его MxNx3, так как im1arr.shape печатает это: (2477, 3700, 3). Второй вариант кажется правильным. - person rem7; 08.02.2009
comment
Кажется, что мне пришлось сначала разделить оба изображения, прежде чем я смогу их добавить, даже если я сделаю клип (мин = 0, макс = 255) на результат, переполнение уже произошло, поэтому причудливые цвета все еще есть. - person rem7; 08.02.2009
comment
Альтернативой делению сначала является преобразование массива байтов в массив int (или короткий), а затем выполнение математики. - person hacken; 08.02.2009