views:

2556

answers:

5
+2  A: 

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 "max(a + b, 256)". The latter seems to be the way that your Matlab example does it.

schnaader
Yes, matlab clamps values when doing arithmetic on uint8 values (e.g. it implicitly does the equivalent to max(double(a)+double(b),256) )"
Mr Fooz
When I try to do max(im1arr+im2arr,256) I get the error:"ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"I do (im1arr+im2arr)/2 I get funky colors, only dimmer, max value 127 so I did:addition=(im1arr/2)+(im2arr/2) and that seems to work.
rem7
A: 

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

hacken
Are the images still not showing? I edited the question and after that, it works here.
schnaader
works for me now. It definitely looks like a wrapping/saturation issue. It would also be nice if you posted your source images.
hacken
I think the pil conversion does make it a MxNx3 since im1arr.shape prints this: (2477, 3700, 3). Option two seems to be correct.
rem7
It seems that I had to divide both images first before I can add them, even if I do a clip(min=0, max=255) on the result, the overflow already happened so the funky colors are still there.
rem7
The alternative to dividing first is to cast from a byte array over to an int (or short) array and then do your math.
hacken
+7  A: 

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')
bpowah
this is especially nice for getting the job done without dragging in numpy.
DarenW
A: 

To clamp numpy array values:

>>> c = a + b
>>> c[c > 256] = 256
J.F. Sebastian
It assumes that type of elements is larger than uint8.
J.F. Sebastian
+5  A: 

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. 8bit). 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 loose information, by squashing the dynamic of the image (you effectively make the images 7bit) before you perform the blending information.

Matalb 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.

Ivan
Thanks, your explanation was very clear.
rem7
Why 'float'? A 'uint16' would be sufficient.
J.F. Sebastian
There was no rational reason for choosing float, uint16 would have been enough indeed.
Ivan