Python 如何将OpenCV cvMat转换回numpy和xFF1F中的ndarray;

Python 如何将OpenCV cvMat转换回numpy和xFF1F中的ndarray;,python,opencv,numpy,Python,Opencv,Numpy,我按照OpenCV cookbook for python接口中的代码将cvMat转换为numpy数组: mat = cv.CreateMat(3,5,cv.CV_32FC1) cv.Set(mat,7) a = np.asarray(mat) 但在我的PC上使用OpenCV 2.1时,它无法工作。结果a这里是一个对象数组,使用“打印a”不会打印a中的所有元素,只打印。因此,如何将OpenCV Mat对象完全转换为原始的numpy.ndarray对象。你是对的,cookbook示例对我也不起作

我按照OpenCV cookbook for python接口中的代码将cvMat转换为numpy数组:

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

但在我的PC上使用OpenCV 2.1时,它无法工作。结果a这里是一个对象数组,使用“打印a”不会打印a中的所有元素,只打印
。因此,如何将OpenCV Mat对象完全转换为原始的numpy.ndarray对象。

你是对的,cookbook示例对我也不起作用,我得到了与你相同的输出(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.]])

对于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_满足opencv.i):

最后,你可以做你的事情:

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)
[1]中的
:将numpy作为npyocv导入opencv
在[2]中:将opencv作为cv导入
在[4]中:将numpy作为npy导入
[12]中:Inpy=npy.zeros((5,5),dtype=npy.float32)
在[13]中:Iocv=npyocv.npymat_as_cvmat_32f(Inpy)
In[14]:Inpy
出[14]:
数组([[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,0,0.]],dtype=float32)
在[15]中:Iocv
出[15]:
在[17]中:cvSetReal2D(Iocv,3,3255)
In[18]:Inpy
出[18]:
数组([[0,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,0.]],dtype=float32)

在调用
np时,尝试将
[:,:]
附加到矩阵中(即使用
mat[:,:]
而不是
mat
),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)
im=cv.CreateImage((5,5,8,1) >>>cv.设置(im,100) >>>im_数组=np.asarray(im) >>>im_阵列 数组(,dtype=object) >>>im_array=np.asarray(im[:,:]) >>>im_阵列 数组([[100100100100100], [100, 100, 100, 100, 100], [100, 100, 100, 100, 100], [100, 100, 100, 100, 100], [100100100100100]],dtype=uint8)
谢谢!这是一个可行的解决方案,但当垫子的尺寸较大时,即远大于3和5,我认为计算“mylist”会浪费很多时间,对吗?@PinkyJie:使用生成器。这是未经测试的,但它可能起作用:MyList=((Mat(i,j)在i(范围)(3))范围内的J(5))@ PLAES:您的解决方案与“Jajin”S.@ PinkyJie相同:这取决于尺寸有多大,以及您认为运行时间过长的原因是什么?测试它…@PinkyJie,plaes建议使用生成器(括号)而不是列表(括号),以便在管理大量数据时节省内存并提高速度。我想你不明白我的问题,你的答案将numpy.ndarray转换为cvMat,但我问的是如何将cvMat转换为numpy.ndarray。如果您想简单地将numpy数组转换为cvMat,我认为有一种简单的方法。这里有一个例子:data=np.array(range(1,9),np.float32)a=cv.CreateMat(2,4,cv.cv_32FC1)cv.SetData(a,data,cv.cv_AUTOSTEP)@PinkyJie,我考虑了处理图像时经常遇到的问题,有时使用Numpy工具,有时使用OpenCV工具,但总是处理内存中的相同数据。您在上面介绍的解决方案在我的系统中引发了一个TypeError:“在方法'cvSetData'中,参数2的类型为'void*”。这是因为OpenCV Python包装器没有正确执行强制转换。我认为我们使用的接口不一样,我使用了从OpenCV 2.0开始的新Python接口,而不是基于swig的Python接口。@PinkyJie,我想这是因为我使用的是Ubuntu的预编译包(Python OpenCV)。可能预编译包正在使用SWIG接口。谢谢你的“记住我”。我用opencv 2.1在我的电脑上测试你的答案,它不起作用。将[:,:]添加到矩阵中仍然会产生错误的输出,如对象数组,您的opencv版本与我的相同吗?@PinkyJie,很抱歉听到它仍然不起作用。我在Ubuntu上使用OpenCV 2.1。差异可能与您使用的Numpy版本有关(使用
np.version.version
来了解-我使用的是1.3版)。真奇怪,我使用的是Numpy 1.5.1
>>> 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)