python - 使用 PyArray_NewFromDescr 存储数据

标签 python cython

我使用 cython,我需要存储数据,如下所示。早些时候,我使用 for 循环将 pus_image[0] 中的数据存储到 3D 数组中,但在运行 n 帧 时,它造成了性能瓶颈。因此,我使用 PyArray_NewFromDescr 来存储,这解决了之前遇到的瓶颈问题。但显示的图像看起来与之前的方法不同,因为我无法增量 _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
<小时/>

您正在做的事情中的错误:

  1. pBuf = <unsigned char *>calloc(sizeInBytes, sizeof(unsigned char))

    在这里,sizeInBytes未初始化,因此您分配的大小是任意的。

  2. 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 ),但选择忽略它并创建您自己的临时对象。

  3. PyArray_NewFromDescr不拥有该数据。因此,一旦使用了它,您就有责任释放它(并且仅当您确定不再需要它时)。你只做一个free ,在循环之后,所以您泄漏了几乎所有分配的内存。要么输入 free在循环中,或 modify the OWNDATA flag授予您的新阵列对阵列的所有权。

<小时/>

总之,除非您对 Python C API 有很好的理解,否则我建议不要使用 PyArray_NewFromDescr并使用 numpy 数组来分配数据。

关于python - 使用 PyArray_NewFromDescr 存储数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50560817/

相关文章:

python - 在 Cython 中将 C++ vector 转换为 numpy 数组而无需复制

c++ - 使用来自 Cython 构造函数的参数初始化 C++ 对象

python - Cython 包装器使用 cl.exe (windows) 将 .c 文件编译为 .pyd

python - 从 C 调用 Python

python - 如何使用 python 中的 mord 模块进行序数回归?

python - 与 Python 字符串大写相反

python - Plotlyplot_trisurf 不适用于排列数组

python - 从双指针(来自 CythonGSL)获取 numpy ndarray (查看,而不是复制)

python - 使用 sharey=<other_axis> 删除子图上的 y 轴刻度标签

python - 绘制 Pandas 时间序列数据框的线性回归线的置信区间