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