2015-05-06 7 views
8

Sto cercando di ottenere Gradient Vector Field di un'immagine usando Python (simile a this matlab question).Sfumatura immagine Campo vettoriale in Python

Questa è l'immagine originale: http:/ /dcc.fceia.unr.edu.ar/~rbaravalle/gradient/test.png

Ecco il mio codice:

import numpy as np 
import matplotlib.pyplot as plt 
import Image 
from PIL import ImageFilter 

I = Image.open('test.png').transpose(Image.FLIP_TOP_BOTTOM) 
I = I.filter(ImageFilter.BLUR) 
p = np.asarray(I) 
w,h = I.size 
y, x = np.mgrid[0:h:500j, 0:w:500j] 

dy, dx = np.gradient(p) 
skip = (slice(None, None, 3), slice(None, None, 3)) 

fig, ax = plt.subplots() 
im = ax.imshow(I, extent=[x.min(), x.max(), y.min(), y.max()]) 
ax.quiver(x[skip], y[skip], dx[skip], dy[skip]) 

ax.set(aspect=1, title='Quiver Plot') 
plt.show() 

Questo è il risultato: http://dcc.fceia.unr.edu.ar/~rbaravalle/gradient/result.png

Il problema è che i vettori sembrano non essere corretto. Questo punto diventa più chiaro quando si ingrandisce l'immagine:

http://dcc.fceia.unr.edu.ar/~rbaravalle/gradient/result2.png

Perché alcuni dei vettori puntano verso il centro come previsto, mentre altri non lo fanno?

Forse c'è un problema con il risultato della chiamata a np.gradient?

risposta

7

Penso che i tuoi strani risultati siano, almeno in parte, perché p è di tipo uint8. Anche diff numpy risulta in valori chiaramente errati per un array di questo dtype. Se si converte in numero intero con segno sostituendo la definizione di p con il seguente: p = np.asarray(I).astype(int8), i risultati di diff sono corretti. Il seguente codice mi dà quello che sembra un campo di ragionevole,

import numpy as np 
import matplotlib.pyplot as plt 
import Image 
from PIL import ImageFilter 

I = Image.open('./test.png') 
I = I.filter(ImageFilter.BLUR) 
p = np.asarray(I).astype('int8') 
w,h = I.size 
x, y = np.mgrid[0:h:500j, 0:w:500j] 

dy, dx = np.gradient(p) 
skip = (slice(None, None, 3), slice(None, None, 3)) 

fig, ax = plt.subplots() 
im = ax.imshow(I.transpose(Image.FLIP_TOP_BOTTOM), 
       extent=[x.min(), x.max(), y.min(), y.max()]) 
plt.colorbar(im) 
ax.quiver(x[skip], y[skip], dx[skip].T, dy[skip].T) 

ax.set(aspect=1, title='Quiver Plot') 
plt.show() 

Questo ha pronunciato la seguente:

Solution

e da vicino questo appare come ci si aspetterebbe,

enter image description here

+0

Grande cattura, '.astype ('int8')' funziona altrettanto bene. È il 'u' (non firmato) che sta creando problemi con gradienti negativi (tagliando valori negativi a valori positivi) – fhdrsdg

+0

È la soluzione, grazie mille! In realtà, ho spostato la chiamata" trasposizione "a im = ax.imshow (I), ieim = ax.imshow (I.transpose (Image.FLIP_TOP_BOTTOM)), e quindi ho ottenuto esattamente lo stesso risultato dell'immagine. Se lo desideri, cambiala in modo che le persone possano utilizzare direttamente il tuo codice. Inoltre, sono d'accordo sul fatto che l'uso di np.int8 sia probabilmente meglio di float. Aggiornamento –

+0

: Una versione "più morbida" può essere ottenuta usando un filtro gaussiano sui gradienti. es .: http://dcc.fceia.unr.edu.ar/~rbaravalle/gradient/resultSoft.png I risultati del codice: http://dcc.fceia.unr.edu.ar/~rbaravalle/gradient/test3. py –