1. 程式人生 > >【數字影象處理】pbm/pgm/ppm圖片的讀寫(Matlab)

【數字影象處理】pbm/pgm/ppm圖片的讀寫(Matlab)

Ø  【作業要求】

1. Get your matlab platform ready. Payspecial attention to the image processing toolbox.

2.Use matlab functions to convert the attached image from .jpg to binary .ppm format. Save it as greens.ppm.

3. Write your own imread(‘*.ppm’) functioncode to read the newly generated .ppm file.

4. Submit your code, result, and report.

選做:嘗試設計你的 .pgm和.pbm讀寫程式。

Ø  【檔案說明】

jpg2ppm.m:

Use matlab functions to convert theattached image from .jpg to binary .ppm format. Save it as greens.ppm

imread_pxm.m:

Myown imread() function code to read .ppm/.pgm/.pbm file which can beencoding ineither ASCII or Binary.

imwrite_pxm.m:

Myown imwrite() function

code to write .ppm/.pgm/.pbm file which canbe encoding ineither ASCII or Binary.

test_imread_pxm.m:

Use imread_pxm() to readgreens.ppm/.pgm/.pbm && greens1.ppm/.pgm/.pbm, then show them to checkthe correctness of function imread_pxm().

test_imwrite_pxm.m:

Use imwrite_pxm to write .ppm/.pgm/.pbmencoding in ASCII/Binary mode, then show them to check the correctness offunction imwrite_pxm().

greens.ppm/.pbm/.pgm(Encoding in Binary) :

Images for imread_pxm() function to load.

greens1.ppm/.pbm/.pgm(Encoding in ASCII) :

Images for imread_pxm() function to load.

Ø  【作業思路】

一、          將jpg檔案轉化成二進位制編碼的.ppm檔案

通過MATLAB自帶的函式imread()載入jpg的影象資料部分,再使用imwrite()將上一步的結果寫成.ppm檔案,’encoding’選項可以選擇’rawbits’和’ASCII’分別是二進位制和ASCII編碼。

二、          手寫imread()實現讀取.ppm/.pgm/.pbm影象的功能

我的imread_pxm()函式可以讀取二進位制或ASCII編碼的.ppm/.pgm/.pbm檔案。主要思路和注意點如下:

1、 影象的頭部統一處理,都是由ASCII編碼的影象型別(P1..P6)、寬、高和畫素值範圍。其中.pbm沒有最後一個畫素值範圍(因為.pbm的畫素值只可能是0/1);

2、 根據影象型別(P1..P6)讀取影象的資料部分,全部按uint8的型別讀入。需要注意P3和P6每個畫素都有RGB資訊,所以需要存入3維矩陣,其他型別存入二維矩陣;

3、 每種型別的影象讀入後的矩陣具有不同的資料型別,fread讀入的結果預設是doublele型別,所以儲存時需要強制轉換:.pgm/.ppm的資料轉換為uint8,.pbm的資料轉換為logical;

4、 ASCII編碼的資料要處理資料間的空格和換行符;

5、 .pbm的影象資料在儲存時需要0/1取反,否則顯示出來的結果會反色;

6、 .pbm的二進位制編碼資料每行會按照8bit對齊,每行最後一個8bit資料的末尾會用0補齊,需要注意處理一下。

使用test_imread_pxm.m指令碼可以測試P1..P6的影象讀入並顯示,以檢測imread_pxm()函式的正確性,結果如下圖:

 

三、          手寫imwrite()實現將畫素值矩陣寫成.ppm/.pgm/.pbm影象的功能

我的imwrite_pxm(im, ptype, filename)函式可以將影象資料矩陣im寫入二進位制或ASCII編碼的.ppm/.pgm/.pbm檔案,ptype指定了影象和編碼的型別(P1..P6),filename指定了儲存檔名,例如imwrite_pxm(im,6, ‘output.ppm’).

實現的主要思路和注意點如下:

1、 統一處理影象的頭部,寫入ASCII編碼的影象型別(P1..P6)、寬、高和畫素值範圍。其中.pbm沒有最後一個畫素值範圍(因為.pbm的畫素值只可能是0/1);

2、 根據影象型別(P1..P6)寫入影象的資料部分,以’wb’格式開啟輸出檔案後,直接使用fwrite()函式寫入即可。需要注意P3和P6每個畫素都有RGB資訊,所以需要寫入3維矩陣,其他型別寫入二維矩陣;

3、 .pbm的影象資料在儲存時需要0/1取反,否則顯示出來的結果會反色;

4、 .pbm的影象資料是由0/1組成的,但是在寫入時,需要將它們合成8bit的數後,再寫入檔案。和上文中提到的一樣,要特殊處理每行最後8bit的對齊。

使用test_imwrite_pxm.m指令碼可以測試P1..P6的影象寫出並顯示,以檢測imwrite_pxm()函式的正確性,結果如下圖:


Ø  【問題】

在手寫imread()函式中處理.pbm二進位制編碼的影象時,我首先嚐試了使用fread(fid, 1, ‘ubit1’),每次讀入1bit,這樣可以直接獲取0/1的資料而不需要每次讀一個uint8,再拆成8個0/1。

但是,我發現在讀入的過程中,每8個bit資料的開頭一個bit的讀入結果都是空(0*0的矩陣)。當我忽略空的結果後,總的資料量比正確結果要少——也就是說1bit為單位讀入會丟失部分資料,而8bit為單位讀入就沒問題。

我查閱了一些資料並沒有找到原因。記錄在此,希望日後可以解決。

上期謎語:日行七千裡(二字數字影象術語)—— 量化