1. 程式人生 > >.pgm圖片簡介以及Python讀取.pgm圖片的方法

.pgm圖片簡介以及Python讀取.pgm圖片的方法

一、什麼是.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模式的讀取。

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()