2009-02-08 18 views
22

Sto provando ad aggiungere due immagini insieme usando NumPy e PIL. Il modo in cui vorrei fare questo in MATLAB sarebbe qualcosa di simile:NumPy, PIL aggiungendo un'immagine

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

Perche 'si ottengono tutti quei colori funky? Ho anche provato a 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 ciò 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 si presento quando sto modificando il palo , ma per qualche motivo le immagini non appaiono nel post.

(le immagini sono state rimosse) 2013 05 09

risposta

28

Come tutti suggerito già, i colori strani che stai osservando è troppo pieno. E come fai notare nel comment of schnaader's answer si ancora ottenere troppo pieno se si aggiungono le immagini in questo modo:

addition=(im1arr+im2arr)/2 

La ragione di questo trabocco è che gli array NumPy (im1arrim2arr) sono di uint8 tipo (cioè 8 bit). Ciò significa che ogni elemento della matrice può contenere solo valori fino a 255, così quando la somma supera 255, si ritorna indietro circa 0:

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

Per evitare di overflow, gli array dovrebbero essere in grado di contenere valori oltre 255. È necessario convertirli in galleggianti per esempio, eseguire l'operazione di miscelazione e convertire il risultato di nuovo a uint8:

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

È non dovrebbe fare questo:

012.351.641,061 mila
addition = im1arr/2 + im2arr/2 

man mano che si perdono le informazioni, schiacciando la dinamica dell'immagine (si rendono effettivamente le immagini a 7 bit) prima di eseguire le informazioni di fusione.

MATLAB nota: la ragione per cui non si vede questo problema in MATLAB, è probabilmente perché MATLAB si occupa dell'overflow implicitamente in una delle sue funzioni.

+0

Grazie, la tua spiegazione è stata molto chiara. – rem7

+1

Perché "fluttuare"? Un 'uint16' sarebbe sufficiente. – jfs

+1

Non c'era un motivo razionale per scegliere float, uint16 sarebbe stato abbastanza vero. – Ivan

2

Sembra il codice che avete inviato riassume solo i valori e valori più grandi di 256 sono stracolmi. Vuoi qualcosa come "(a + b)/2" o "min (a + b, 256)". Quest'ultimo sembra essere il modo in cui lo fa l'esempio di Matlab.

+0

Sì, i valori dei morsetti matlab quando si esegue l'aritmetica su valori uint8 (ad esempio implicitamente l'equivalente a max (double (a) + double (b), 256)) " –

+0

Quando provo a fare max (im1arr + im2arr, 256) Ho ricevuto l'errore: "ValueError: il valore di verità di una matrice con più di un elemento è ambiguo. Usa a.any() o a.all() " I do (im1arr + im2arr)/2 ottengo colori funky, solo dimmer, valore massimo 127, quindi ho fatto: addizione = (im1arr/2) + (im2arr/2) e sembra funzionare. – rem7

+1

Non vuoi realmente 'min (a + b, 256)' perché se ottieni un valore superiore a 256 vuoi bloccare il valore a 256 (non vuoi prendere un valore superiore a 256. In ogni caso, per correggere l'errore @ rem7 sottolineato, si può fare 'additionF = np.minimum (im1arrF + im2arrF, 256)' – Vincent

0

Le immagini di esempio non vengono visualizzate da me quindi ho intenzione di fare un po 'di ipotesi.

Non riesco a ricordare esattamente come funziona la conversione da numpy a pil ma ci sono due casi probabili. Sono sicuro al 95% che sia 1 ma sto dando 2 solo nel caso in cui mi sbaglio. 1) 1 im1Arr è un array MxN di interi (ARGB) e quando si aggiungono im1arr e im2arr insieme si sta traboccando da un canale al successivo se i componenti b1 + b2> 255. Immagino che matlab rappresenti le loro immagini come array MxNx3 in modo che ogni canale di colore sia separato. Puoi risolvere questo problema dividendo i canali immagine PIL e creando array numpy

2) 1 im1Arr è un array MxNx3 di byte e quando aggiungi im1arr e im2arr insieme, stai avvolgendo il componente.

È inoltre necessario ridimensionare l'intervallo tra 0-255 prima della visualizzazione. Le tue scelte sono dividere per 2, ridimensionare per 255/array.max() o fare una clip. Non so cosa faccia il MATLAB

+0

Le immagini non vengono ancora visualizzate? Ho modificato la domanda e dopo – schnaader

+0

funziona per me ora, sembra decisamente un problema di wrapping/saturazione, sarebbe anche bello se hai postato le tue immagini di origine – hacken

+0

Penso che la conversione pil lo faccia un MxNx3 dato che le stampe im1arr.shape questo: (2477, 3700, 3). L'opzione 2 sembra corretta – rem7

17

L'utilizzo della miscela PIL() con un valore alfa di 0.5 equivale a (im1arr + im2arr)/2. La fusione non richiede che le immagini abbiano livelli alfa.

Prova questo:

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

questo è particolarmente bello per portare a termine il lavoro senza trascinarlo in intorpidimento. – DarenW

1

per bloccare NumPy valori di matrice:

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

Presume che il tipo di elementi sia maggiore di uint8. – jfs