2011-04-23 15 views
9

sigo el código en OpenCV libro de cocina para la interfaz de Python para transformar cvMat a numpy matriz:?cómo transformar un cvMat OpenCV de nuevo a ndarray en numpy

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

pero con OpenCV 2.1 en mi PC, no lo hace trabajo. El resultado a aquí es una matriz de objetos, usando "imprimir a" no imprime todos los elementos en a, solo imprime <cvmat(type=42424005 rows=3 cols=5 step=20)>. Entonces, ¿cómo transformar por completo un objeto OpenCV Mat al original objeto numpy.ndarray.

Respuesta

9

Trate de usar añadiendo a [:,:] la matriz (es decir. use mat[:,:] en lugar de mat) en su llamada al np.asarray - haciendo esto también permitirá que asarray trabaje en imágenes.

Su ejemplo:

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

Y para una imagen:

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

¡Gracias! ¡Esa es la manera más fácil! – PinkyJie

+0

pruebo tu respuesta en mi PC con opencv 2.1, no funcionó. Agregar ** [:,:] ** a la matriz todavía dio el resultado incorrecto como matriz de objetos, ¿su versión de opencv es la misma que la mía? – PinkyJie

+0

@PinkyJie, siento escuchar que todavía no funcionó. Estoy usando OpenCV 2.1 en Ubuntu. La diferencia podría tener que ver con la versión de Numpy que está usando (use 'np.version.version' para averiguarlo - Estoy usando la versión 1.3). – rroowwllaanndd

1

Tiene razón, el ejemplo del libro de cocina tampoco funciona para mí y obtengo el mismo resultado que el suyo (win xp, python 2.6.6, opencv 2.1., Numpy 1.5.1).

Tal vez se puede usar algo similar 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

Gracias! Esa es una solución factible, pero cuando la dimensión del Mat es grande, es decir, mucho más grande que 3 y 5, creo que el cálculo de "mylist" perderá mucho tiempo, ¿no? – PinkyJie

+0

@PinkyJie: use generadores. Esto no se ha probado, pero podría funcionar: mylist = ((mat [i, j] para i en rango (3)) para j en el rango (5)) – plaes

+0

@plaes: tu solución es la misma con @joaquin 's. – PinkyJie

2

Para la versión 2.1 de OpenCV, si es necesario cuota de la memoria y si no se preocupan por un poco de programación C y el TRAGO envoltura, podría intentar esta solución que he usado durante algún tiempo:

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

crear un encabezado, por ejemplo, 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); 

y un archivo de interfaz (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" 

Compilar:

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 

Por último, usted puede hacer sus cosas:

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

Creo que no entendiste mi pregunta, tu respuesta se convirtió numpy.ndarray en cvMat, pero lo que pregunté fue cómo convertir cvMat a numpy.ndarray. Si desea simplemente convertir la matriz numpy a cvMat, creo que hay una manera fácil. Aquí hay un ejemplo: data = np.array (rango (1,9), np.float32) a = cv.CreateMat (2,4, cv.CV_32FC1) cv.SetData (a, data, cv.CV_AUTOSTEP) – PinkyJie

+0

@PinkyJie, consideré el problema recurrente para trabajar en una imagen, a veces usando herramientas Numpy, otras usando herramientas OpenCV, pero siempre trabajando con los mismos datos en la memoria. La solución que presentó arriba generó un TypeError en mi sistema: "en el método 'cvSetData', argumento 2 de tipo 'void *". Eso es porque las envolturas de OpenCV Python no están realizando el casting correctamente. –

+0

Creo que las interfaces que utilizamos no son las mismas, utilicé la nueva interfaz de python a partir de opencv 2.0, no la interfaz de python basada en swig. – PinkyJie

Cuestiones relacionadas