python - 使用 PyArray_NewFromDescr 存储数据
问题描述
我使用 cython,我需要存储数据,如下所示。早些时候,我使用 for 循环将数据存储pus_image[0]
到 3D 数组中,但在运行n frames
它时会产生性能瓶颈。因此,我曾经PyArray_NewFromDescr
存储解决了之前面临的瓶颈问题。但是显示的图像看起来与以前的方法不同,因为我无法进行 increment _puc_image += aoiStride
。谁能帮我解决这个问题。
代码 1:
def LiveAquisition(self,nframes,np.ndarray[np.uint16_t,ndim = 3,mode = 'c']data):
cdef:
int available
AT_64 sizeInBytes
AT_64 aoiStride
AT_WC string[20]
AT_WC string1[20]
AT_WC string2[20]
AT_WC string3[20]
unsigned char * pBuf
unsigned char * _puc_image
int BufSize
unsigned int i, j, k, l = 0
for i in range(nframes):
pBuf = <unsigned char *>calloc(sizeInBytes, sizeof(unsigned char))
AT_QueueBuffer(<AT_H>self.cameraHandle, pBuf, sizeInBytes)
print "Frame number is :",
print i
response_code = AT_WaitBuffer(<AT_H>self.cameraHandle, &pBuf, &BufSize, 500)
_puc_image = pBuf
pus_image = <unsigned short*>pBuf
for j in range(self.aoiWidth/self.hbin):
pus_image = <unsigned short*>(_puc_image)
for k in range(self.aoiHeight/self.vbin):
data[l][j][k] = pus_image[0]
pus_image += 1
_puc_image += aoiStride
free(pBuf)
return data
代码2:使用PyArray_NewFromDescr
之前其定义为:
from cpython.ref cimport PyTypeObject
from python_ref cimport Py_INCREF
cdef extern from "<numpy/arrayobject.h>":
object PyArray_NewFromDescr(PyTypeObject *subtype, np.dtype descr,int nd, np.npy_intp* dims,np.npy_intp*strides,void* data, int flags, object obj)
def LiveAquisition(self,nframes,np.ndarray[np.uint16_t,ndim = 3,mode = 'c']data):
cdef:
int available
AT_64 sizeInBytes
AT_64 aoiStride
AT_WC string[20]
AT_WC string1[20]
AT_WC string2[20]
AT_WC string3[20]
unsigned char * pBuf
unsigned char * _puc_image
int BufSize
unsigned int i, j, k, l = 0
np.npy_intp dims[2]
np.dtype dtype = np.dtype('<B')
for i in range(nframes):
pBuf = <unsigned char *>calloc(sizeInBytes, sizeof(unsigned char))
AT_QueueBuffer(<AT_H>self.cameraHandle, pBuf, sizeInBytes)
print "Frame number is :",
print i
response_code = AT_WaitBuffer(<AT_H>self.cameraHandle, &pBuf, &BufSize, 500)
Py_INCREF(dtype)
dims[0] = self.aoiWidth
dims[1] = self.aoiHeight
data[i,:,:] = PyArray_NewFromDescr(<PyTypeObject *> np.ndarray, np.dtype('<B'), 2,dims, NULL,pBuf, np.NPY_C_CONTIGUOUS, None)
free(pBuf)
return data
解决方案
您执行此操作的方式存在一些大错误。但是,您所做的完全没有必要,并且有一种更简单的方法。您可以简单地使用 Numpy 分配数据,并获取该数组的第一个元素的地址:
# earlier
cdef unsigned char[:,::1] p
# in loop
p = np.array((self.aoiWidth,self.aoiHeight),dtype=np.uint8)
pbuf = &p[0,0] # address of first element of p
# code goes here
data[i,:,:] = p
你正在做的错误:
pBuf = <unsigned char *>calloc(sizeInBytes, sizeof(unsigned char))
在这里,
sizeInBytes
未初始化,因此您分配的大小是任意的。PyArray_NewFromDescr
窃取对descr
论点的引用。这意味着它不会增加参数的引用计数。线PyArray_NewFromDescr(<PyTypeObject *> np.ndarray, np.dtype('<B'), ...)
将被翻译为 Cython 之类的东西
temp_dtype = np.dtype('<B') # refcount 1 PyArray_NewFromDescr(<PyTypeObject *> np.ndarray, temp_dtype, ...) # temp_dtype refcount is still 1 Py_DECREF(temp_dtype) # Cython's own cleanup # temp_dtype has now been destroyed, but is still being used by your array
看起来您复制了一些正确处理此问题的代码(
Py_INCREF(dtype)
然后将其传递给PyArray_NewFromDescr
),但选择忽略它并创建您自己的临时对象。PyArray_NewFromDescr
不拥有数据。因此,您有责任在它被使用后重新分配它(并且只有在您确定不再需要它时)。你只做一个free
, 在循环之后,所以你几乎泄漏了你分配的所有内存。要么将 置于free
循环中,要么修改OWNDATA
标志以赋予您的阵列的新阵列所有权。
总之,除非您对 Python C API 有很好的理解,否则我建议不要使用PyArray_NewFromDescr
和使用 numpy 数组来分配数据。
推荐阅读
- firebase - 在 gunicorn 上的 Flask 中使用 eventlet 和 Firebase 时,关键工作人员超时
- ios - 自己的警报控制器
- c# - 使用反射设置工具提示
- typescript - 如何使用 react-native-webview-leaflet?
- json - 在 Elm 中,如何解码嵌套 JSON 中的 JSON 对象
- apache-spark - 使用动态 partitionOverwriteMode 将 DataFrame 写入由多列分区的 HDFS 上的镶木地板
- html - 如何在带有空格的 HTML 标记中编写内联 Ruby on Rails 三元运算符?
- azure - 如何检索应用服务计划实例名称 (RDXXXXX)?
- html - 如何使用css制作圆形img
- postgresql - INSERT INTO 排除 ID 列违反主键唯一性约束