在Python中读取pgm文件

10

我希望在Python中将pgm文件作为数值文件/矩阵读取。

目前我使用以下方式打开文件:

f = open('/home/matthew/NCM/mdb001.pgm', 'rb')

当我读到第一行时,它看起来和预期的一样。

r.readline()
产生。
'P5\n'

下一行也很好

'1024 1024\n'

接下来的内容

'255\n'

但是我得到了一系列的乱码。它看起来像一些十六进制值混在其他东西里面。

我不想把文件视为图片,我只想以这种格式查看它。


1
你正在按照你所链接的文档阅读P5风格的pgm文件。你看到的“胡言乱语”是以字节编码的像素数据,其范围在'\x00'到最大值之间,而你显示的最大值为255(或'\xff')。应该有1024×1024字节的“胡言乱语”表示图像数据。 - msw
好的,那么我该如何将它显示为数字数据(可能用空格分隔),而不是十六进制值等等? - Matt Cremeens
看起来不仅仅是十六进制值,还有其他一些东西。像这样的 :;;=><@>??A?@A@??@?A?BEBACADAHHFEEHHFIFFEGKJLLJLMJKKJIJJFJFHHIGIIIHIILIKLNRNNSTUY]lw - Matt Cremeens
3个回答

10

在阅读您所展示的标题后,您已获得了宽度(1024)、高度(下一个1024)和深度(255)。为了获取像素数据,最简单的方法是逐字节地读取它们:

def read_pgm(pgmf):
    """Return a raster of integers from a PGM as a list of lists."""
    assert pgmf.readline() == 'P5\n'
    (width, height) = [int(i) for i in pgmf.readline().split()]
    depth = int(pgmf.readline())
    assert depth <= 255

    raster = []
    for y in range(height):
        row = []
        for y in range(width):
            row.append(ord(pgmf.read(1)))
        raster.append(row)
    return raster

这段代码仅适用于8位深度的图像,这就是为什么存在assert语句的原因。

对于PGM文件,将头信息放在一行上是合法的,例如:

P5 1024 1024 15
如果您遇到这样的文件,read_pgm 将会有明显的失败;处理这种情况的代码留给读者自己去练习。

1
我也学习到了PIL似乎很好地处理了这种类型的图像文件读取。非常感谢您的时间和努力。 - Matt Cremeens

5

msw的回答引导我编写了以下函数,用于读取具有他所描述的头文件的16位.pmg图像:

def read_pgm(pgmf):
"""Return a raster of integers from a PGM as a list of lists."""
   header = pgmf.readline()
   assert header[:2] == b'P5'
   (width, height) = [int(i) for i in header.split()[1:3]]
   depth = int(header.split()[3])
   assert depth <= 65535

   raster = []
   for y in range(height):
       row = []
       for y in range(width):
           low_bits = ord(pgmf.read(1))
           row.append(low_bits+255*ord(pgmf.read(1)))
       raster.append(row)
   return raster

f = open(pgm_path, 'rb')
im = read_pgm(f)
f.close()
im = np.array(im)

我希望这能阐明如何使用之前给出的答案。

1

有趣的是,Matplotlib已经内置了这个功能。

以下代码应该可以输出与@GodsFighter答案相同的结果。

import matplotlib.pyplot as plt
with open(f, 'rb') as pgmf:
    im = plt.imread(pgmf)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接