Domanda

Sto cercando di aggiungere due immagini insieme utilizzando NumPy e PIL. Il modo in cui vorrei fare questo in MATLAB sarebbe qualcosa di simile:

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

ottengo qualcosa di simile:

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

Utilizzando un programma di composizione e aggiungendo le immagini il risultato MATLAB sembra essere di destra.

In Python che sto cercando di fare la stessa cosa in questo modo:

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

e ottengo qualcosa di simile:

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

Perché ricevo tutti quei colori funky? Ho anche provato ad utilizzare ImageMath.eval("a+b", a=im1, b=im2), ma ottengo un errore su RGB non supportato.

ho anche visto che c'è un Image.blend(), ma che richiede un alfa.

Qual è il modo migliore per ottenere quello che sto cercando?

Immagini sorgente (le immagini sono state rimosse):

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

Humm, OK, così ho aggiunto le immagini di origine utilizzando l'icona immagine aggiuntivo e mostrano quando sto modificando il post, ma per qualche motivo le immagini non si presenta nel post.

(le immagini sono state rimosse) 2013 05 09

È stato utile?

Soluzione

As everyone suggested already, the weird colors you're observing are overflow. And as you point out in the comment of schnaader's answer you still get overflow if you add your images like this:

addition=(im1arr+im2arr)/2

The reason for this overflow is that your NumPy arrays (im1arr im2arr) are of the uint8 type (i.e. 8-bit). This means each element of the array can only hold values up to 255, so when your sum exceeds 255, it loops back around 0:

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

To avoid overflow, your arrays should be able to contain values beyond 255. You need to convert them to floats for instance, perform the blending operation and convert the result back to uint8:

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

You should not do this:

addition = im1arr/2 + im2arr/2

as you lose information, by squashing the dynamic of the image (you effectively make the images 7-bit) before you perform the blending information.

MATLAB note: the reason you don't see this problem in MATLAB, is probably because MATLAB takes care of the overflow implicitly in one of its functions.

Altri suggerimenti

Using PIL's blend() with an alpha value of 0.5 would be equivalent to (im1arr + im2arr)/2. Blend does not require that the images have alpha layers.

Try this:

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

It seems the code you posted just sums up the values and values bigger than 256 are overflowing. You want something like "(a + b) / 2" or "min(a + b, 256)". The latter seems to be the way that your Matlab example does it.

To clamp numpy array values:

>>> c = a + b
>>> c[c > 256] = 256

Your sample images are not showing up form me so I am going to do a bit of guessing.

I can't remember exactly how the numpy to pil conversion works but there are two likely cases. I am 95% sure it is 1 but am giving 2 just in case I am wrong. 1) 1 im1Arr is a MxN array of integers (ARGB) and when you add im1arr and im2arr together you are overflowing from one channel into the next if the components b1+b2>255. I am guessing matlab represents their images as MxNx3 arrays so each color channel is separate. You can solve this by splitting the PIL image channels and then making numpy arrays

2) 1 im1Arr is a MxNx3 array of bytes and when you add im1arr and im2arr together you are wrapping the component around.

You are also going to have to rescale the range back to between 0-255 before displaying. Your choices are divide by 2, scale by 255/array.max() or do a clip. I don't know what matlab does

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top