.pgm图片简介以及Python读取.pgm图片的方法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/quiet_girl/article/details/80904471

一、什么是.pgm图片?

.pgm文件由于模式的不同其数据存储方式也有所不同,下面介绍P2和P5模式的.pgm文件的格式。

1、P2模式的.pgm文件

P2模式的.pgm文件存储如下图所示:
这里写图片描述
其内容释义如下:

①第一行内容“P2”表示.pgm文件的模式。
②第二行“128, 120”表示图片的宽度、图片的高度。
③第三行“156”表示图片数据的最大值。
④第三行之后的文件表示图片的像素值,其是按行存放的。每个像素使用字符串来表示,比如灰度值可能的最大值为255,它的第一行第一列的像素值为100,那么该图像每个像素使用3个Ascii字符表示,第一行第一列数据为Ascii表示的”100”。*注意:P2格式文件数据部分当数据超过70个字节的时候,会自动换行。也就是说图像的每一行数据末尾,或者存储时超过70个字节时,需要进行换行。

2、P5模式的.pgm文件

P5模式的.pgm文件存储如下图所示(使用Notepad++打开的效果图):
这里写图片描述
其内容释义如下:

①第一行内容“P5”表示.pgm文件的模式。
②第二行“64, 60”表示图片的宽度、图片的高度。
③第三行“156”表示图片数据的最大值。
④第三行之后的文件表示图片的像素值。每个像素用可以用二进制表示。比如灰度值可能的最大值为255,它的第一行第一列像素值为100,那么该图像每个像素使用一个字节表示,第一行第一列为数值为100的二进制一个字节表示。如果灰度值可能的最大值是65535,那么它的第一行第一列为数值为100的二进制,使用两个字节表示(因为表示到65535需要两个字节)。对于P2模式的.pgm文件,每个像素数据之间没有间隔的连续存储,图像一行信息结束后从下一行第一列继续,两行图像数据之间也没有间隔的连续存储,直到将图像的所有信息表示完。

二、Python读取.pgm图片

1、读取P4~P6模式的.pgm图片

在读取以.pgm为扩展名的图片时,我们注意到模式有P2、P5等。这些模式的读取方式不同,对于P4~P6的模式,可以使用PIL非常方便的进行读取,如下代码。

from PIL import Image

def read_img():
    im = Image.open("./data/faces.tar/faces/an2i/an2i_left_angry_open_4.pgm")    # 读取文件
    im.show()    # 展示图片
    print(im.size)   # 输出图片大小

if __name__ == "__main__":
    read_img()     # 调用read_img()

即一句话便可以方便的读取.pgm图片,获取其像素点。

1、读取P2模式的.pgm图片

但是在使用上述方法读取P2模式的.pgm图片时,会报出如下错误:
这里写图片描述
错误信息提示使用PIL这种方式不可以读取此图片文件,经过一番资料的查找发现原因是:

Pillow only supports the binary versions of the PPM formats, P4-6, not the ascii versions: P1-3.
即PIL只支持二进制格式的P4-P6模式的读取,而不支持Ascii码格式的P1-P3模式的读取。

在pillow源码的模式定义为也对上述限定有所体现(源码地址:https://github.com/python-pillow/Pillow/blob/master/src/PIL/PpmImagePlugin.py#L27),如下图:
这里写图片描述
因此,P1-P3模式的图片无法使用PIL进行读取,读取方法如下:

import numpy as np
import matplotlib.pyplot as plt

def readpgm(name):    # 读取图片
    with open(name) as f:
        lines = f.readlines()

    # Ignores commented lines
    for l in list(lines):
        if l[0] == '#':
            lines.remove(l)

    # Makes sure it is ASCII format (P2)
    assert lines[0].strip() == 'P2'

    # Converts data to a list of integers
    data = []
    for line in lines[1:]:
        data.extend([int(c) for c in line.split()])   # 读取数据

    return (np.array(data[3:]),(data[1],data[0]),data[2])

data = readpgm('./data/faces.tar/faces/an2i/an2i_left_angry_open.pgm')   # 返回值data[0]为数据,data[1]为shape,data[2]为出现的最大数据。

print(data)
plt.imshow(np.reshape(data[0],data[1])) #
plt.show()


参考资料:
https://github.com/python-pillow/Pillow/issues/860
https://www.cnblogs.com/liulijin/p/6840436.html
https://blog.csdn.net/colourful_sky/article/details/70244485

猜你喜欢

转载自blog.csdn.net/quiet_girl/article/details/80904471
PGM