使用PIL fromarray导入RGB数组生成PNG显示异常,求原因及正确方法
问题描述
想用PIL的fromarray方法把RGB数组导入并保存为带元数据的PNG,代码如下:
import numpy as np from PIL import Image from PIL.PngImagePlugin import PngInfo a = np.array([[[255, 0, 0], [0, 255, 0]], # 红 绿 [[0, 0, 255], [0, 0, 0]]]) # 蓝 黑 img = Image.fromarray(a, mode="RGB") metadata = PngInfo() # 需要添加元数据,所以用Pillow而不是cv2 metadata.add_text("key", "value") img.save("test.png", pnginfo=metadata)
但输出图像显示为红 黑 黑 黑,而非预期的红 绿 蓝 黑。尝试RGBA数组也出现类似问题:
a = np.array([[[255, 0, 0, 255], [0, 255, 0, 255]], # 红 绿 [[0, 0, 255, 255], [0, 0, 0, 255]]]) # 蓝 黑
原因分析
numpy创建数组时默认的dtype是int64,而PIL的fromarray在处理RGB/RGBA模式时,要求输入数组必须是uint8类型(0-255的无符号整数)。当传入int64类型的数组时,PIL无法正确解析数值(即便表面数值在0-255范围内,但类型不匹配),导致除第一个像素外的其他像素被识别为无效值,最终显示为黑色。
解决方法
创建numpy数组时显式指定dtype=np.uint8,或者将已有数组转换为uint8类型即可。
修正后的RGB代码
import numpy as np from PIL import Image from PIL.PngImagePlugin import PngInfo # 显式指定dtype为uint8 a = np.array([[[255, 0, 0], [0, 255, 0]], [[0, 0, 255], [0, 0, 0]]], dtype=np.uint8) img = Image.fromarray(a, mode="RGB") metadata = PngInfo() metadata.add_text("key", "value") img.save("test.png", pnginfo=metadata)
修正后的RGBA代码
import numpy as np from PIL import Image from PIL.PngImagePlugin import PngInfo a = np.array([[[255, 0, 0, 255], [0, 255, 0, 255]], [[0, 0, 255, 255], [0, 0, 0, 255]]], dtype=np.uint8) img = Image.fromarray(a, mode="RGBA") metadata = PngInfo() metadata.add_text("key", "value") img.save("test_rgba.png", pnginfo=metadata)
如果数组已经创建完成,也可以通过a = a.astype(np.uint8)转换类型后再传入fromarray。
内容的提问来源于stack exchange,提问作者Basj
相关产品推荐
相关产品推荐

