PIL.Image.fromarray() 要求数组 shape 为 (h,w)、(h,w,3) 或 (h,w,4),dtype 为 uint8;float 数组需先缩放并转 uint8,CHW 格式需转 HWC,否则报错或图像异常。

用 PIL.Image.fromarray() 转 NumPy 数组为图像对象
NumPy 数组转图像的核心就是 PIL.Image.fromarray(),它能直接把形状为 (h, w)、(h, w, 3) 或 (h, w, 4) 的数组变成可操作的 Image 对象。但前提是数组 dtype 和值域得“对味”:
-
uint8是最稳妥的选择;若数组是float64或值在[0, 1]区间,直接传进去会生成全黑或异常色块——PIL 默认按uint8解释,0.5会被截断成0 - 灰度图要确保是 2D(
(h, w))且 dtype 为uint8;RGB 图必须是 3D 且最后一维长度为 3,顺序是 HWC(不是 CHW) - 如果数组是
float32且范围是[0.0, 1.0],先做(arr * 255).astype(np.uint8);如果是[-1.0, 1.0],得先线性映射:((arr + 1) * 127.5).astype(np.uint8)
保存前务必检查数组 shape 和 dtype
常见报错 TypeError: Cannot handle this data type 或保存出来是纯色/噪点图,90% 出在 shape/dtype 不匹配。尤其注意以下几点:
- 模型输出的 tensor 或 array 常是 CHW 格式(如
(3, h, w)),PIL 要 HWC,得先np.transpose(arr, (1, 2, 0)) - 单通道 float 数组(如
(h, w)+float32)不能直接给fromarray();要么转uint8,要么显式指定 mode:fromarray(arr, mode='F')(但后续 save 不支持'F',还得转回uint8) - 用
print(arr.shape, arr.dtype, arr.min(), arr.max())快速验证,比猜快得多
保存时选对格式和参数避免失真
Image.save() 看似简单,但 JPEG 会压缩、PNG 默认不带 alpha、TIFF 支持 float —— 格式选错会导致精度丢失或通道被丢弃:
- JPEG 只支持
L(灰度)和RGB,且强制转uint8;保存 float 数组会静默截断,不报错但数据已毁 - PNG 支持
RGBA,但如果源数组是(h, w, 4)且第 4 通道是 float,得先转uint8,否则 alpha 通道可能全 0 或溢出 - 需要保留浮点精度(比如科研可视化中间结果),改用 TIFF:
img.save("out.tiff"),它原生支持float32,但注意大多数看图软件打不开
完整可跑的一行检查模板
调试时别写一堆临时变量,用这行快速验证能否走通:
立即学习“Python免费学习笔记(深入)”;
from PIL import Image; import numpy as np
arr = np.random.rand(100, 100, 3) # 示例数组
img = Image.fromarray((arr * 255).astype(np.uint8)) # 关键转换
img.save("test.png")只要这行不崩,说明路径、dtype、shape 都过关;崩了就顺着报错往回查 arr 的 shape、dtype、min/max。实际项目里,建议把转换逻辑封装成函数,加 assert 检查,而不是靠运气。
最容易被忽略的是:模型输出、cv2 读入、matplotlib 归一化后的数组,三者默认值域和 dtype 全不同,混着用必出问题。每次接新数据源,先 print 三连再动手。


















