2011-04-23 64 views
9

Tôi làm theo các mã trong OpenCV sách dạy nấu ăn cho giao diện python để chuyển CvMat để NumPy mảng:làm thế nào để biến một CvMat OpenCV trở lại ndarray trong NumPy

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

nhưng với OpenCV 2.1 trên máy tính của tôi, nó không công việc. Kết quả a đây là mảng đối tượng, sử dụng "in" không in tất cả phần tử trong a, chỉ in <cvmat(type=42424005 rows=3 cols=5 step=20)>. làm thế nào để biến đổi hoàn toàn một đối tượng OpenCV Mat đối tượng OpenCV thành đối tượng numpy.ndarray.

Trả lời

9

Hãy thử sử dụng phụ [:,:] để ma trận (ví dụ: sử dụng mat[:,:] thay vì mat) trong cuộc gọi của bạn tới np.asarray - thực hiện việc này cũng sẽ cho phép asarray hoạt động trên hình ảnh.

dụ của bạn:

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

Và đối với một hình ảnh:

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

Cảm ơn bạn !!! Đó là cách dễ nhất! – PinkyJie

+0

tôi kiểm tra câu trả lời của bạn trên PC của tôi với opencv 2.1, nó không hoạt động. Phụ thêm ** [:,:] ** vào ma trận vẫn cho đầu ra sai như mảng đối tượng , là phiên bản opencv của bạn giống với của tôi? – PinkyJie

+0

@PinkyJie, xin lỗi khi biết điều đó vẫn không hoạt động. Tôi đang sử dụng OpenCV 2.1 trên Ubuntu. Sự khác biệt có thể liên quan đến phiên bản Numpy bạn đang sử dụng (sử dụng 'np.version.version' để tìm hiểu - tôi đang sử dụng phiên bản 1.3). – rroowwllaanndd

1

Bạn nói đúng, ví dụ về nấu ăn không có tác dụng đối với tôi và tôi nhận được kết quả tương tự như của bạn (win xp, python 2.6.6, opencv 2.1., Numpy 1.5.1).

lẽ bạn có thể sử dụng một cái gì đó tương tự như:

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

Cảm ơn bạn! Đó là một giải pháp khả thi, nhưng khi kích thước của Mat lớn, tức là lớn hơn 3 và 5, tôi nghĩ rằng việc tính toán "danh sách của tôi" sẽ lãng phí rất nhiều thời gian, phải không? – PinkyJie

+0

@PinkyJie: sử dụng máy phát điện. Đây là chưa được kiểm tra, nhưng nó có thể hoạt động: mylist = ((mat [i, j] cho i trong phạm vi (3)) cho j trong phạm vi (5)) – plaes

+0

@plaes: giải pháp của bạn giống với @joaquin 's. – PinkyJie

2

Đối với phiên bản 2.1 của OpenCV, nếu bạn cần phải phần bộ nhớ và nếu bạn không quan tâm đến một chút về lập trình C và SWIG gói, bạn có thể thử giải pháp này mà tôi sử dụng trong một thời gian:

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

Tạo một tiêu đề, ví dụ, 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); 

và một tập tin giao diện (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 

Cuối cùng, bạn có thể làm công cụ của bạn:

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

Tôi nghĩ rằng bạn không hiểu câu hỏi của tôi, câu trả lời của bạn chuyển đổi numpy.ndarray thành cvMat, nhưng những gì tôi hỏi là làm thế nào để chuyển đổi cvMat thành numpy.ndarray. Nếu bạn muốn chỉ đơn giản là chuyển đổi mảng numpy để cvMat, tôi nghĩ rằng có một cách dễ dàng. Dưới đây là ví dụ: data = np.array (dải ô (1,9), np.float32) a = cv.CreateMat (2,4, cv.CV_32FC1) cv.SetData (a, data, cv.CV_AUTOSTEP) – PinkyJie

+0

@PinkyJie, tôi xem xét vấn đề thường xuyên để làm việc trên một hình ảnh, đôi khi sử dụng các công cụ Numpy, thời gian khác bằng cách sử dụng các công cụ OpenCV, nhưng luôn luôn làm việc trên cùng một dữ liệu trong bộ nhớ. Giải pháp mà bạn đã trình bày ở trên đã đưa ra một TypeError trong hệ thống của tôi: "in method 'cvSetData', đối số 2 của loại 'void *". Đó là bởi vì trình bao bọc Python OpenCV không hoạt động đúng cách. –

+0

Tôi nghĩ rằng các giao diện chúng tôi sử dụng không giống nhau, tôi đã sử dụng giao diện python mới bắt đầu từ opencv 2.0, không phải là giao diện python dựa trên swig. – PinkyJie

Các vấn đề liên quan