使用 Python 3.6 将二维 rgb 矩阵转换为 PNG 图像

Conversion 2-dimensional rgb matrix to PNG Image with Python 3.6

提问人:Uwe_98 提问时间:10/2/2019 最后编辑:Uwe_98 更新时间:10/9/2019 访问量:1639

问:

我需要使用 Python 3.6 转换 24 维 3.6 位 rgb- 矩阵

[[rr11gg11bb11, rr12gg12bb12,..  ..,rr1mgg1mbb1m],
.
.
 [rri1gg11bb11, rr12ggi2bb12,..  ..,rr1mgg1mbb1m]
.
.
 [rrn1ggn1bbn1, rrn2ggn2bbn2,.. ..,rrmnggmnbbmn]]

转换为 TIF、PNG 和 JPG 格式的图像。

我还得到了文件形式的矩阵

image.bin.

从这个二进制文件中,我可以借助 RAW 像素查看器对图像进行编辑:

http://rawpixels.net/ 

我找到了 PIL 库,但我没有找到任何从这些数据构建图像对象的方法。我该怎么做?我使用 Python 3.6。

现在我尝试了以下方法:

im = Image.frombuffer('RGB', (self.width, self.height), self.matrix, 'raw', 
'RGB', 0, 1)              
logger.info("image object created.")
im.save('result.png')
logger.info("image saved as result.png")

但我得到的信息是:

TypeError: a bytes-like object is required, not 'list'

现在我发现我必须将对象转换为字节数组:

 npm = np.array(self.matrix)
 arr = bytearray(npm)
 print(arr)
 im = Image.frombuffer('RGB', (self.width, self.height), arr, 'raw', 
'RGB', 0, 1)        

当我使用“L”或“RGBA”时,转换会起作用,但不能使用“RGB”。奇怪的是,在这种情况下,它拒绝字节数组对象。

python-3.x 图像 矩阵 png 数据转换

评论

1赞 Mark Setchell 10/2/2019
看这里。。。stackoverflow.com/a/58075903/2836621您将需要而不是.'RGB''L'
0赞 Uwe_98 10/2/2019
@MarkSetchell 这似乎是我的矩阵。所以我做了以下工作:ba
0赞 Mark Setchell 10/2/2019
不要把代码放在评论区。如果它不起作用,请将其添加到您的问题中,如果有效,则将其添加为答案。然后接受它是正确的并抓住要点:-)
0赞 Uwe_98 10/2/2019
@MarkSetchell好的,我已经这样做了。但它不会创建图像。我以为我不必进行您的链接中显示的第一步,因为我已经拥有了矩阵。

答:

3赞 Mark Setchell 10/2/2019 #1

更新的答案

因此,从本质上讲,您没有 Numpy 数组,但您有一个列表列表,其中每个元素都是一个 24 位数字,代表一个 RGB 三元组 RGB888。

所以,我可以像这样表示你的列表:

f=[ 
[0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x000000,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF],
[0xFFFFFF,0xFFFFFF,0xFFFFFF,0x000000,0x000000,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF],
[0xFFFFFF,0xFFFFFF,0x000000,0xFFFFFF,0x000000,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF],
[0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x000000,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF],
[0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0x000000,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF,0xFFFFFF]
] 

因此,我可以将其转换为 uint32 元素的 Numpy 数组,如下所示:

na = np.array(f).astype(np.uint32) 

然后制作一个 PIL 喜欢使用的 RGB 数组:

h,w = 5,10
RGB=np.zeros((h,w,3),dtype=np.uint8)

然后我只需要将三胞胎移位并复制到正确的位置:

RGB[:,:,0] = na>>16            # Take red from top
RGB[:,:,1] = (na>>8) & 0xff    # Take green from middle
RGB[:,:,2] = na & 0xff         # Take blue from bottom

现在,我可以从该RGB阵列制作PIL图像并将其保存到磁盘:

pIm = Image.fromarray(RGB).save('result.png')

原始答案

让我们使用 ImageMagick 创建一个测试数据文件。首先作为 PNG,这样你就可以看到它:

magick -size 640x480 gradient:magenta-yellow image.png

enter image description here

现在又是同样的事情,但这次是RGB888来匹配你的文件:

magick -size 640x480 gradient:magenta-yellow -depth 8 rgb:image.bin

现在:

from PIL import Image

# Open the file and read contents into "data"
with open('image.bin','rb') as f: 
    data = f.read() 

# Convert that into PIL Image
im = Image.frombuffer('RGB', (640, 480), data, 'raw', 'RGB', 0, 1)

# Save
im.save('result.png')

同样,您可以让 Numpy 读取文件,然后将结果转换为 PIL 图像:

import numpy as np

im = Image.fromarray(np.fromfile('image.bin',dtype=np.uint8).reshape(480,640,3))

如果你想检查你的二进制文件是否真的包含你认为它包含的内容,你也可以用ImageMagick将其转换为PNG来测试它。假设您认为文件是 640 像素宽 x 480 像素高和 RGB888,您可以要求 ImageMagick 将其转换为 PNG:

magick -depth 8 -size 640x480 RGB:<YOURFILENAME> image.png

或者,如果您认为它是具有 128 字节标头的单个 16 位单通道灰度图像,则要忽略该图像:

magick -depth 16 -size 640x480+128 GRAY:<YOURFILENAME> image.png

关键词:原始、原始图像、二进制文件、图像、图像处理、Python、ImageMagick、转换。

评论

1赞 Mark Setchell 10/2/2019
请注意,您不需要再次执行第一步 - 我只是创建虚拟数据,因为问题中没有提供任何数据。
0赞 Uwe_98 10/3/2019
谢谢,Magick文件转换有效,否则将数组转换为png文件仍然会带来麻烦。
1赞 Mark Setchell 10/3/2019
好的,问题要么是你以错误的方式读取你的文件,要么是你的文件不是你所想的那样。所以请分享你的文件:-)如果您不想将其发布在公共网站上,欢迎您发送电子邮件至 [email protected] 还请说出图像的高度和宽度以及哪个是哪个。即 N 像素宽和 M 像素高。
0赞 Uwe_98 10/8/2019
不 不。。您发布的有关将 bin 文件转换为 png 的建议效果很好。即使没有使用 magick 的第一行代码。但现在我被要求将二维 24 位矩阵直接转换为 tif、png、jpeg 格式。只有这一点让我感到麻烦——正如我问题的下半部分所描述的那样。你能再帮我一次吗?谢谢。
0赞 Mark Setchell 10/8/2019
@Uwe_98 您尚未提供图片。你只描述了你的图像,所以我做了一个符合你的描述,代码读取了它。所以代码是正确的。唯一的可能性是你的图像与描述不符,所以在你提供图像之前,我不能做任何其他事情。请提供您的图片。