2011-04-23 3 views
9

Я следую код в OpenCV поваренной книги для интерфейса питона, чтобы преобразовать cvMat в Numpy массива:?как преобразовать OpenCV cvMat обратно ndarray в NumPy

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

но с OpenCV 2.1 на моем компьютере, он не Работа. Результат a здесь представляет собой массив объектов, используя «print a» не распечатывает весь элемент в a, только печать <cvmat(type=42424005 rows=3 cols=5 step=20)>. поэтому, как полностью преобразовать объект OpenCV Mat в исходный numpy.ndarray объект.

ответ

9

Попробуйте использовать добавление [:,:] к матрица (т. используйте mat[:,:] вместо mat) по вашему звонку по номеру np.asarray - это также позволит asarray работать с изображениями.

Ваш пример:

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

И для изображения:

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

Спасибо !!! Это самый простой способ! – PinkyJie

+0

Я тестирую ваш ответ на своем ПК с opencv 2.1, это не сработало. Добавление ** [:,:] ** к матрице все же дало неверный результат, например массив объектов, ваша версия opencv такая же, как у меня? – PinkyJie

+0

@PinkyJie, жаль слышать, что он все еще не работает. Я использую OpenCV 2.1 на Ubuntu. Разница может быть связана с версией Numpy, которую вы используете (используйте 'np.version.version', чтобы узнать - я использую версию 1.3). – rroowwllaanndd

1

Вы правы, пример поваренной книги не работает ни для меня, и я получаю тот же результат, что и ваш (win xp, python 2.6.6, opencv 2.1., Numpy 1.5.1).

Может быть, вы можете использовать что-то подобное:

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

Спасибо! Это приемлемое решение, но когда размер Мата большой, то есть намного больше 3 и 5, я думаю, что расчет «mylist» будет тратить много времени, не так ли? – PinkyJie

+0

@ PinkyJie: использовать генераторы. Это не проверено, но может работать: mylist = ((mat [i, j] для i в диапазоне (3)) для j в диапазоне (5)) – plaes

+0

@plaes: ваше решение аналогично с @joaquin. – PinkyJie

2

Для версии OpenCV 2.1, если вам нужно долю памяти и если вы не заботитесь о немного программирования C и SWIG упаковка, вы можете попробовать это решение, которое я использовал в течение некоторого времени:

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

Создать заголовок, например, 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); 

и файл интерфейса (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 

Наконец, вы можете сделать свой материал:

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

Я думаю, что вы не поняли мой вопрос, ваш ответ преобразовал numpy.ndarray в cvMat, но я спросил, как преобразовать cvMat в numpy.ndarray. Если вы хотите просто преобразовать массив numpy в cvMat, я думаю, что есть простой способ. Вот пример: data = np.array (диапазон (1,9), np.float32) a = cv.CreateMat (2,4, cv.CV_32FC1) cv.SetData (a, data, cv.CV_AUTOSTEP) – PinkyJie

+0

@PinkyJie, я рассматривал текущую проблему для работы с изображением, иногда используя инструменты Numpy, иногда используя инструменты OpenCV, но всегда работая с одними и теми же данными в памяти. Вышеупомянутое решение подняло TypeError в моей системе: «в методе« cvSetData », аргумент 2 типа« void * ». Это потому, что оболочки OpenCV Python не выполняют кастинг должным образом. –

+0

Я думаю, что интерфейсы, которые мы использовали, не совпадают, я использовал новый интерфейс python, начиная с opencv 2.0, а не на основе swig-интерфейса python. – PinkyJie

Смежные вопросы