2012-01-23 9 views
8

Ho un setup in Python dove uso la libreria OpenCV per leggere i frame di un video come array 2D - questi video sono in scala di grigi, quindi sono utilizzando numeri interi a 8 bit senza segno per i valori dei pixel.Mostra array 2D da OpenCV in Matplotlib.pyplot.imshow()

Nel passaggio successivo, sto cercando di utilizzare pyplot.imshow() da matplotlib per visualizzare la cornice del video. Sfortunatamente, sto ricevendo qualcosa che non ha alcun senso.

Ecco il codice per leggere il video:

import numpy as np 
import cv 

def read_video(filename): 
    video = cv.CaptureFromFile('%s' % filename) 
    num_frames = int(cv.GetCaptureProperty(video, cv.CV_CAP_PROP_FRAME_COUNT)) 

    frames = [] 
    for i in range(0, num_frames): 
    frame = cv.QueryFrame(video) 
    if frame is None: 
     quit('Failed to extract frame %s of %s!' % (i, num_frames)) 
    toadd = cv2numpy(frame, 'uint8') 
    frames.append(np.array(toadd)) 
    return np.array(frames) 

cv2numpy è una funzione di utilità che converte l'array OpenCV in una matrice NumPy (solo una chiamata al fromstring e poi un reshape). Ecco il codice che sto usando per tracciare il primo fotogramma del video:

import matplotlib.pyplot as plot 
import matplotlib.cm as cm 

frames = read_video('video.avi') 
plot.imshow(frames[0], cmap = cm.gray) 
plot.show() 

In qualche altro codice, ho usato l'OpenCV SaveImage su un singolo fotogramma per fornire un riferimento per quello che ci si aspetterebbe da imshow. Here's the image I get from the former e here's the image I get from the code above.

Come potete vedere sono molto diversi. L'unica cosa che posso ricavare dall'immagine reale è lo striping: sembra quasi che abbia sbagliato le dimensioni, che ci siano più pixel nella larghezza dell'altezza (questa immagine dovrebbe essere 128 x 256). Ma ho provato a trasporre l'array prima di tracciarlo, modificando i parametri e come per lo imshow documentation e, con l'eccezione di alcuni strani strappi di pixel, non ho trovato una soluzione.

Qualche idea?

EDIT 1: Immagino può essere prudente per aggiungere il codice cv2numpy, nel caso in cui rimodellamento è in qualche modo cavarsela cose (dal momento che la mia immagine "verità" di cui sopra non utilizzare quel codice e quindi cv2numpy è coinvolto solo nella conduttura discutibile).

def cv2numpy(cvarr, the_type): 
    a = np.fromstring(
     cvarr.tostring(), 
     dtype = the_type, 
     count = cvarr.width * cvarr.height) 
    a.shape = (cvarr.height, cvarr.width) 
    return a 

risposta

5

Credo che il problema sia con la funzione cv2numpy. Prova questo:

def cv2numpy(cvarr, the_type): 
    a = np.asarray(cv.GetMat(cvarr), dtype=the_type) 
    return a 

Ha fatto il trucco per me. Se non stai utilizzando un input in scala di grigi (so che hai detto che stai usando la scala di grigi ora), dovrai convertire utilizzando cv.CreateImage e cv.CvtColor.

+0

Questo era esattamente il problema. OpenCV stava ancora leggendo i video come RGB, quindi ho aggiunto in 'cv.CreateImage' e' cv.CvtColor', ho stampato l'immagine e sembra esattamente come mi aspettavo. Grazie mille! Apparentemente la conversione degli array OpenCV in array numpy tramite stringhe non è ottimale. – Magsol

1

Si sta utilizzando la versione 2.3.1? Usando l'API cv2, non è più necessario implementare la nostra versione di conversione OpenCV/Numpy. Ad esempio, il codice seguente funziona correttamente:

>>> import cv2 
>>> from matplotlib import pyplot as plt 
>>> lenna = cv2.imread('lenna.tiff', cv2.CV_LOAD_IMAGE_GRAYSCALE) 
>>> lenna 
array([[162, 162, 162, ..., 170, 155, 128], 
     [162, 162, 162, ..., 170, 155, 128], 
     [162, 162, 162, ..., 170, 155, 128], 
     ..., 
     [ 43, 43, 50, ..., 104, 100, 98], 
     [ 44, 44, 55, ..., 104, 105, 108], 
     [ 44, 44, 55, ..., 104, 105, 108]], dtype=uint8) 
>>> plt.imshow(lenna, cmap='gray') 
>>> plt.show() 
+0

Questa potrebbe essere una domanda stupida, ma come posso determinare la versione di OpenCV che sto usando? Tutto quello che vedo è un'opzione '.__ version__', ma mi dice solo la revisione. – Magsol

+0

@Magsol, le versioni recenti di OpenCV presentano entrambe le interfacce. Puoi usare "import cv" e "import cv2". Prova "import cv2" e guarda cosa ottieni. Usa anche il tuo sistema di gestione dei pacchetti per trovare la versione OpenCV che hai nel tuo sistema.Oppure compila dalle fonti (vedi http://goo.gl/8ds4i). –

+0

La documentazione su OpenCV Sphinx mostra entrambe le interfacce, ma l'interfaccia cv è considerata "legacy". http://opencv.itseez.com/ –