多维数组和位图数据的转换

作者:袖梨 2026-06-18
多维数组与位图数据的转换是同一像素集合的不同表达:图像转位图需缩放、灰度化、二值化、packbits打包为字节数组;位图还原需frombuffer、reshape、unpackbits;深度学习输入需按框架要求调整维度顺序;须区分位图与BMP文件,注意reshape与transpose差异、自适应阈值及MSB位序。

多维数组和位图数据的转换,核心在于理解二者的数据组织逻辑:位图本质是按行优先排列的二值(或灰度)像素序列,而多维数组(如 NumPy 的 ndarray)则用结构化维度描述空间布局。转换不是格式切换,而是对同一像素集合的不同视角表达。

图像转位图数组(用于嵌入式显示)

典型场景是把一张图片转成适合 OLED 或 LCD 屏幕直接读取的字节数组(如 128×64 单色屏)。关键步骤是尺寸适配 → 灰度 → 二值化 → 按字节打包:

  • 先缩放到目标分辨率(如 img.resize((128, 64))),确保宽高匹配硬件;
  • 转灰度后用阈值二值化:np.array(img.convert("L")) > 128 得到布尔矩阵;
  • 每 8 个像素合并为 1 字节(高位在前):用 np.packbits() 自动完成,输出形状为 (height, width//8)
  • 若需 C 风格十六进制数组(如 {0x01, 0xFF, ...}),再用 .tobytes().hex() 拆分并格式化。

位图数组还原为多维数组

从嵌入式设备导出的位图数据(如 bytes 或 list of int),要复原为可处理的数组,重点是明确原始布局:

  • 若已知是单色、128×64 屏数据,且按行存储、每字节 8 像素,则先转为 uint8 数组:np.frombuffer(data, dtype=np.uint8)
  • reshape 成 (64, 128//8),再用 np.unpackbits() 展开为 (64, 128) 布尔数组;
  • 如需灰度或彩色,位图数据本身不含调色信息,必须额外携带 palette 或通道说明——纯位图(BMP 文件头除外)不包含颜色模型。

PyTorch/TensorFlow 输入所需的维度对齐

深度学习框架对输入张量有固定轴约定(如 PyTorch 是 [C, H, W],TensorFlow 常用 [H, W, C]),图像加载后常需调整:

  • PIL 加载默认是 [H, W, C](RGB 为 3),转 Tensor 后用 .permute(2, 0, 1) 变成 [C, H, W]
  • 灰度图 PIL 返回 [H, W],需先 .unsqueeze(0) 补通道维,再转为 [1, H, W]
  • 批量数据堆叠时,确保所有样本 shape 一致;若原始是 [N, H, W, C],模型要 [N, C, H, W],就用 transpose(0, 3, 1, 2)moveaxis

避免常见陷阱

转换容易出错的地方不在代码语法,而在语义误解:

  • 别混淆“位图”和“BMP 文件”:前者指像素二值/灰度阵列,后者是带文件头、信息头、调色板的完整二进制格式;
  • reshape 不等于 transposea.reshape(3,4) 改形状但保持内存顺序;a.transpose() 交换轴索引,影响后续切片和广播;
  • 二值化阈值不是万能的:光照不均时用全局阈值会丢失细节,应考虑局部自适应方法(如 OpenCV 的 cv2.adaptiveThreshold);
  • 字节序与位序要统一:OLED 驱动常要求 MSB 在前(即第 0 像素对应最高位),np.packbits(..., bitorder='big')(NumPy 1.23+)可显式控制。

相关文章

精彩推荐