使用PyArray_NewFromDescr存储数据时图像显示异常求助
解决Cython中PyArray_NewFromDescr替代循环后的图像错位问题
我来帮你分析问题根源,以及如何快速修复:
你的核心困扰是原代码通过_puc_image += aoiStride实现了相机缓冲区的非连续行跳转,但改用PyArray_NewFromDescr时没有适配这种内存布局,再加上两个容易忽略的细节错误,最终导致图像显示异常。
问题拆解
先对比两段代码的核心逻辑差异:
原循环代码(代码1)的关键逻辑
相机返回的pBuf内存并非紧密排列的二维数组——每行像素之间存在额外填充字节,所以你通过_puc_image += aoiStride跳到下一行的起始位置;同时还做了hbin和vbin的像素合并,最终存储的是降采样后的图像。
新代码(代码2)的三个核心问题
- 数据类型不匹配:原数据是
unsigned short(16位,对应numpy的uint16),但你用了<B(8位无符号字符),导致像素值被截断。 - 忽略非连续内存的步长:你给
PyArray_NewFromDescr传了NULL作为strides,默认会创建连续内存数组,但相机缓冲区每行的步长是aoiStride(远大于aoiWidth * sizeof(uint16_t)),直接赋值会把填充字节当成有效像素,导致图像错位。 - 未处理Binning降采样:原代码对图像做了
hbin和vbin的降采样,但新代码直接用原始尺寸赋值,导致图像尺寸和内容不匹配。
修复方案
针对这些问题,修改代码如下:
1. 修正类型与步长定义
在函数的cdef块中添加步长数组,并指定正确的数据类型:
def LiveAquisition(self,nframes,np.ndarray[np.uint16_t,ndim = 3,mode = 'c']data): cdef: # ... 保留原有变量定义 ... np.npy_intp dims[2] np.npy_intp strides[2] # 新增步长数组,用于定义非连续内存布局 np.dtype dtype = np.dtype('<u2') # 改为uint16类型,匹配原数据的unsigned short
2. 计算正确的维度与步长
在每帧处理时,结合hbin和vbin设置对应参数:
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 // self.hbin dims[1] = self.aoiHeight // self.vbin # 设置步长:完全对应原代码的内存跳转逻辑 strides[0] = self.hbin * sizeof(unsigned short) # 列方向每跳一个bin,移动hbin个像素的字节数 strides[1] = self.vbin * aoiStride # 行方向每跳一个bin,移动vbin行的步长字节数 # 创建带自定义步长的numpy数组,直接包装相机缓冲区 frame_array = PyArray_NewFromDescr( <PyTypeObject *> np.ndarray, dtype, 2, dims, strides, pBuf, np.NPY_C_CONTIGUOUS | np.NPY_WRITEABLE, # 确保数组可写 None ) # 将降采样后的帧赋值到目标3D数组 data[i,:,:] = frame_array free(pBuf) return data
关键说明
- 步长的作用:
strides数组定义了数组在每个维度上移动一个元素需要跳过的字节数,这里的设置完全对应原代码中pus_image +=1和_puc_image += aoiStride的逻辑,同时结合了hbin和vbin的降采样需求。 - 数据类型匹配:
'<u2'对应Cython的unsigned short,避免了像素值的截断。 - 性能保持:
PyArray_NewFromDescr直接包装相机的内存缓冲区,不需要逐像素循环,完全保留了新方法的性能优势。
这样修改后,图像应该就能和原循环方法的结果一致了,同时解决了n帧处理的性能瓶颈。
内容的提问来源于stack exchange,提问作者aishwarya selvaraj
相关产品推荐
相关产品推荐

