如何从ctypes.POINTER缓冲区创建带自定义步幅/行大小的numpy ndarray
处理带行填充的RGB位图内存布局
要正确处理带有行填充(比如Windows GDI+的24位RGB位图)的内存缓冲区,核心是手动指定numpy数组的步幅(strides),告诉numpy每个维度上移动一个元素需要跳过多少字节。具体修改如下:
修改后的代码
import ctypes import numpy as np # 假设已有image对象,包含height、width、ptr属性 height = image.height width = image.width ptr = image.ptr # 计算实际行步幅(带填充的每行字节数) row_stride = 4 * ((3 * width + 3) // 4) # 定义数组的shape和strides shp = (height, width, 3) # strides单位为字节:(行步幅, 单个像素字节数, 单个通道字节数) strides = (row_stride, 3, 1) # 将原生指针转换为numpy数组并指定自定义strides ptr_ubyte = ctypes.cast(ptr, ctypes.POINTER(ctypes.c_ubyte)) arr = np.ctypeslib.as_array(ptr_ubyte, shape=shp).view() arr.strides = strides
关键说明
- 行步幅计算:按照Windows GDI+的规则,24位RGB位图的行字节数会向上取整到4的倍数,公式
4 * ((3 * width + 3) // 4)用于计算该值。 - strides参数:numpy的strides定义了数组各维度移动一个元素的字节跨度:
- 高度维度:每移动一行,跳过一整行的字节数(含填充),即
row_stride - 宽度维度:每移动一个像素,跳过3字节(对应RGB三个通道)
- 通道维度:每移动一个通道,跳过1字节
- 高度维度:每移动一行,跳过一整行的字节数(含填充),即
- view()的作用:创建共享数据的数组视图,避免直接修改原数组默认strides可能引发的异常。
也可以直接用np.ndarray构造数组,效果一致:
arr = np.ndarray( shape=shp, dtype=np.uint8, buffer=ctypes.cast(ptr, ctypes.c_void_p).value, strides=strides )
内容的提问来源于stack exchange,提问作者ceztko
相关产品推荐
相关产品推荐

