2015-06-13 21 views
7

Sto scrivendo un codice che parte di esso sta leggendo una fonte di immagini e mostrandola sullo schermo per l'utente con cui interagire. Ho anche bisogno dei dati più nitidi delle immagini. Io uso il seguente per leggere i dati e visualizzarli in pyGameCome presentare una matrice numpy nella superficie di pygame?

def image_and_sharpen_array(file_name): 
    #read the image data and return it, with the sharpened image 
    image = misc.imread(file_name) 

    blurred = ndimage.gaussian_filter(image,3) 
    edge = ndimage.gaussian_filter(blurred,1) 
    alpha = 20 
    out = blurred + alpha*(blurred - edge) 
    return image,out 

#get image data 
scan,sharpen = image_and_sharpen_array('foo.jpg') 
w,h,c = scan.shape 


#setting up pygame 
pygame.init() 
screen = pygame.display.set_mode((w,h)) 

pygame.surfarray.blit_array(screen,scan) 
pygame.display.update() 

e l'immagine viene visualizzata sullo schermo solo ruotato e invertita. Ciò è dovuto a differenze tra misc.imread e pyGame? O è dovuto a qualcosa di sbagliato nel mio codice?

C'è un altro modo per farlo? La maggior parte delle soluzioni che ho letto riguardavano il salvataggio della figura e la lettura con `` pyGame ''.

risposta

1

Ogni libreria ha il proprio modo di interpretare gli array di immagini. Con "ruotato" suppongo che intendi trasposto. Questo è il modo in cui PyGame mostra array numpy. Ci sono molti modi per farlo sembrare 'corretto'. In realtà ci sono molti modi anche per mostrare la matrice, che ti dà il pieno controllo sulla rappresentazione del canale e così via. In pygame versione 1.9.2, questo è il rendering di array più veloce che potrei mai ottenere. (Nota per la versione precedente non funzionerà!). Questa funzione riempire la superficie con matrice:

def put_array(surface, myarr):   # put array into surface 
    bv = surface.get_view("0") 
    bv.write(myarr.tostring()) 

Se questo non funziona, utilizzare questo, dovrebbe funzionare ovunque:

# put array data into a pygame surface 
def put_arr(surface, myarr): 
    bv = surface.get_buffer() 
    bv.write(myarr.tostring(), 0) 

Probabilmente ancora ottenere non ciò che si vuole, per cui è trasposta o hanno scambiato canali di colore. L'idea è di gestire i tuoi array in quella forma, che offre questo buffer di superficie. Per scoprire quale sia l'ordine dei canali e l'ordine degli assi corretti, utilizzare la libreria openCV (cv2.imread (nome file)). Con openCV apri le immagini nell'ordine BGR come standard e ha molte funzioni di conversione. Se ricordo correttamente, quando si scrive direttamente sul buffer di superficie, BGR è l'ordine corretto per 24 bit e BGRA per una superficie a 32 bit. Quindi puoi provare a mettere l'array di immagini che ottieni fuori dal file con questa funzione e blitare sullo schermo.

Esistono altri modi per disegnare gli array, ad es. ecco tutto un insieme di funzioni di supporto http://www.pygame.org/docs/ref/surfarray.html
Ma non lo consiglierei di usarlo, poiché le superfici non sono per la manipolazione diretta dei pixel, probabilmente vi perderete nei riferimenti. Piccolo suggerimento: per fare 'test di segnalazione' usa un'immagine, come questa. Quindi vedrai immediatamente se qualcosa non va, basta caricare come array e provare a renderizzare.

enter image description here

1

Il mio suggerimento è quello di utilizzare il modulo pygame.transform. Esistono i metodi flip e rotate, che è possibile utilizzare per la trasformazione. Guarda i documenti su questo.

Il mio consiglio è di salvare l'immagine di uscita su un nuovo Surface, quindi applicare le trasformazioni e blittare sul display.

temp_surf = pygame.Surface((w,h)) 
pygame.surfarray.blit(temp_surf, scan) 

'''transform temp_surf''' 

screen.blit(temp_surf, (0,0)) 

Non ho idea del motivo. Probabilmente è qualcosa a che fare con l'ordine in cui gli assi vengono trasferiti da un array 2d a un pygame Surface.

0

spesso impiegare il metodo NumPy swapaxes(): In questo caso abbiamo solo bisogno di invertire xe asse y (numero dell'asse 0 e 1) prima di visualizzare la nostra gamma:

return image.swapaxes(0,1),out 
1

Ho pensato che tecnico fornisse una buona soluzione - solo un po 'magra su informazioni. Supponendo get_arr() è una funzione che restituisce l'array di pixel:

pixl_arr = get_arr() 
pixl_arr = numpy.swapaxes(pixl_arr, 0, 1) 
new_surf = pygame.pixelcopy.make_surface(pixl_arr) 
screen.blit(new_surf, (dest_x, dest_y)) 

In alternativa, se si sa che l'immagine sarà sempre delle stesse dimensioni (come nel scorrendo fotogrammi di un file video o gif), è sarebbe più efficace di riutilizzare la stessa superficie:

pixl_arr = get_arr() 
pixl_arr = numpy.swapaxes(pixl_arr, 0, 1) 
pygame.pixelcopy.array_to_surface(old_surf, pixl_arr) 
screen.blit(old_surf, (dest_x, dest_y)) 

YMMV, ma finora questo sta lavorando bene per me.