2011-04-23 13 views
9

seguo il codice in OpenCV libro di cucina per l'interfaccia python di trasformare cvMat a NumPy matrice:?come trasformare un cvMat OpenCV torna a ndarray in NumPy

mat = cv.CreateMat(3,5,cv.CV_32FC1) 
cv.Set(mat,7) 
a = np.asarray(mat) 

ma con OpenCV 2.1 sul mio PC, non è così lavoro. Il risultato a qui è un array di oggetti, utilizzando "print a" non stampa tutto l'elemento in a, stampa solo <cvmat(type=42424005 rows=3 cols=5 step=20)>. quindi come trasformare completamente un oggetto OpenCV Mat nell'oggetto numpy.ndarray originale.

risposta

9

Provare a utilizzare aggiungendo [:,:] a la matrice (es. utilizzare mat[:,:] anziché mat) nella chiamata a np.asarray - ciò consentirà anche di utilizzare asarray per le immagini.

Il vostro esempio:

>>> import cv 
>>> import numpy as np 
>>> mat = cv.CreateMat(3 , 5 , cv.CV_32FC1) 
>>> cv.Set(mat , 7) 
>>> a = np.asarray(mat[:,:]) 
>>> a 
array([[ 7., 7., 7., 7., 7.], 
     [ 7., 7., 7., 7., 7.], 
     [ 7., 7., 7., 7., 7.]], dtype=float32) 

E per un'immagine:

>>> im = cv.CreateImage((5 , 5) , 8 , 1) 
>>> cv.Set(im , 100) 
>>> im_array = np.asarray(im) 
>>> im_array 
array(<iplimage(nChannels=1 width=5 height=5 widthStep=8)>, dtype=object) 
>>> im_array = np.asarray(im[:,:]) 
>>> im_array 
array([[100, 100, 100, 100, 100], 
     [100, 100, 100, 100, 100], 
     [100, 100, 100, 100, 100], 
     [100, 100, 100, 100, 100], 
     [100, 100, 100, 100, 100]], dtype=uint8) 
+0

Grazie !!! Questo è il modo più semplice! – PinkyJie

+0

collaudo la tua risposta sul mio PC con opencv 2.1, non ha funzionato. L'aggiunta di ** [:,:] ** alla matrice ha dato comunque l'output sbagliato come array di oggetti, la tua versione opencv è uguale alla mia? – PinkyJie

+0

@PinkyJie, mi spiace di sentirlo ancora non ha funzionato. Sto usando OpenCV 2.1 su Ubuntu. La differenza potrebbe avere a che fare con la versione di Numpy che stai usando (usa 'np.version.version' per scoprirlo - sto usando la versione 1.3). – rroowwllaanndd

1

Hai ragione, l'esempio di ricettario non funziona nemmeno per me e ottengo lo stesso risultato del tuo (vinci xp, python 2.6.6, opencv 2.1., Numpy 1.5.1).

Forse si può usare qualcosa di simile a:

>>> mat = cv.CreateMat(3,5,cv.CV_32FC1) 
>>> cv.Set(mat,7) 
>>> mylist = [[mat[i,j] for i in range(3)] for j in range(5)] 
>>> ar = np.array(mylist) 
>>> ar 
array([[ 7., 7., 7.], 
     [ 7., 7., 7.], 
     [ 7., 7., 7.], 
     [ 7., 7., 7.], 
     [ 7., 7., 7.]]) 
+0

Grazie! Questa è una soluzione praticabile, ma quando la dimensione del Tappetino è grande, cioè molto più grande di 3 e 5, penso che il calcolo della "lista" sprecherà molto tempo, giusto? – PinkyJie

+0

@PinkyJie: usa i generatori. Questo non è testato, ma potrebbe funzionare: mylist = ((mat [i, j] per i in range (3)) per j nella gamma (5)) – plaes

+0

@plaes: la tua soluzione è la stessa di @joaquin. – PinkyJie

2

Per la versione 2.1 di OpenCV, se avete bisogno di quota la memoria e se non si preoccupano di un po 'di programmazione C e SWIG avvolgimento, si potrebbe provare questa soluzione che ho usato per qualche tempo:

CvMat * npymat_as_cvmat_32f(float * npymat_float, int rows, int cols) 
{ 
    CvMat * cvmat; 

    cvmat = cvCreateMatHeader(rows, cols, CV_32FC1); 
    cvSetData(cvmat, npymat_float, cols * sizeof(float)); 

    return cvmat; 
} 

creare un'intestazione, ad esempio, mat_conversion.h:

/* npymat_as_cvmat_32f 
* 
* Create an OpenCV CvMat that shared its data with the input NumPy double array 
*/ 
CvMat * npymat_as_cvmat_32f(float * npymat_float, int rows, int cols); 

e un file di interfaccia (numpy_meets_opencv.i):

/* numpy_meets_opencv */ 
%module numpy_meets_opencv 

%{ 
#define SWIG_FILE_WITH_INIT 
#include <cv.h> 
#include "mat_conversion.h" 
%} 

%include "numpy.i" 

%init %{ 
import_array(); 
%} 

%apply (float* INPLACE_ARRAY2, int DIM1, int DIM2) {(float* npymat_float, int rows, int cols)}; 

%include "mat_conversion.h" 

Compile:

numpy_meets_opencv: numpy_meets_opencv.i mat_conversion.c 
     swig -python -classic numpy_meets_opencv.i 
     $(CC) $(NPY_CFLAGS) -fPIC -fno-stack-protector -c mat_conversion.c `pkg-config --cflags $(PKGS)`   
     $(CC) $(NPY_CFLAGS) -fPIC -fno-stack-protector -c numpy_meets_opencv_wrap.c `pkg-config --cflags $(PKGS)` 
     ld -shared mat_conversion.o numpy_meets_opencv_wrap.o `pkg-config --libs $(PKGS)` -o _numpy_meets_opencv.so 

Infine, è possibile fare le tue cose:

In [1]: import numpy_meets_opencv as npyocv 
In [2]: import opencv as cv 
In [4]: import numpy as npy 
In [12]: Inpy = npy.zeros((5,5), dtype=npy.float32) 
In [13]: Iocv = npyocv.npymat_as_cvmat_32f(Inpy) 
In [14]: Inpy 
Out[14]: 
array([[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.]], dtype=float32) 
In [15]: Iocv 
Out[15]: <opencv.cv.CvMat; proxy of <Swig Object of type 'CvMat *' at 0x30e6ed0> > 
In [17]: cv.cvSetReal2D(Iocv, 3,3, 255) 
In [18]: Inpy 
Out[18]: 
array([[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 255., 0.], 
     [ 0., 0., 0., 0., 0.]], dtype=float32) 
+0

Penso che tu non abbia capito la mia domanda, la tua risposta ha convertito numpy.ndarray in cvMat, ma quello che ho chiesto è come convertire cvMat in numpy.ndarray. Se vuoi semplicemente convertire numpy array in cvMat, penso che ci sia un modo semplice. Ecco un esempio: data = np.array (range (1,9), np.float32) a = cv.CreateMat (2,4, cv.CV_32FC1) cv.SetData (a, data, cv.CV_AUTOSTEP) – PinkyJie

+0

@PinkyJie, ho considerato il problema ricorrente lavorare su un'immagine, a volte usando gli strumenti Numpy, altre volte usando gli strumenti OpenCV, ma lavorando sempre sugli stessi dati in memoria. La soluzione che hai presentato sopra ha generato un errore TypeError nel mio sistema: "nel metodo 'cvSetData', argomento 2 di tipo 'void *". Questo perché i wrapper Python OpenCV non eseguono correttamente il casting. –

+0

Penso che le interfacce che abbiamo usato non siano le stesse, ho usato la nuova interfaccia python a partire da opencv 2.0, non l'interfaccia python basata su swig. – PinkyJie

Problemi correlati