2012/10/17 20:43:
介紹:
這次作業是利用C#完成的,程式介面如圖一所示,而我針對本次作業是著重於實現直方圖均化的效果,而直方圖的部份只有基本樣子呈現。另外,由於C#本身不希望使用者使用指標的功能,因此對外開放一般讀寫的method讓使用者存取各個圖片的pixel值,但這種作法對於影像處理的效能並不好,而C#本身還是帶有指標功能,只是一般預設為不可使用,若要使用則必須在在組態設定部分開啟同意unsafe區塊,如此使用者便可使用類似於Borland C++ Builder的ScanLine方式讀取圖片,但實際用法卻頗為複雜,針對此部份的實際做法將於最後做介紹。
(圖一)
接下來將展現直方圖均化的效果,圖二是在學校CC棟三樓所拍攝,將手機相機的ISO值降到最低即可達到這樣的效果。利用圖一所示的直方圖可以繪製出目前色彩的分佈,如圖三所示,由圖可得知所有色彩分布都在最暗的部份,所以整張照片看上去是漆黑一片。
(圖二)
(圖三)
接著是利用圖一所示的均化來調整整張圖片的色彩分布,圖四為圖二均化後的樣子,而圖五則是均化後的色彩分布圖。
(圖四)
(圖五)
心得:
針對圖四的部份懷疑是否因演算法錯誤或是畫素問題導致均化後的圖片看上去顏色並不自然,而且噪點極多,整張照片的成像品質並不好。
另外,先前所提到在C#利用類似於Borland C++ Builder的ScanLine方式的作法是:
1. Project -> "XXX" Properties... -> Build 將Allow unsafe code勾起
2. 利用Bitmap提供的LockBits方法來將圖片鎖定到記憶體中
3. 利用BitmapData取得該圖記憶體位址
4. 利用BitmapData提供的Scan0方法取得每列的圖片像素點(類似於ScanLine)
這裡要注意的是,C#處理圖片的方式是將每個像素點以四個byte方式存入(因CPU存取記憶體是以WORD方式讀取,所以對於程式存放資料時會做Memory Alignment),然而圖片像素的顏色只有三個byte,因此BitmapData還提供一個叫做Stride的屬性,該屬性表示每一列之長度,因此,若讀取圖片後需要換行時則需將地址加上Stride減去處理過的像素點個數,如此便可正常處理圖片。
題外話:
因我的程式撰寫方式是引入一個存放圖片的位置,之後將該位置內的所有圖片全部加入程式中,但假設圖片畫素過大以及圖片過多時,會造成程式類似於當機的狀態,針對此部份是另外新增一個thread去執行這部份,用以解決若圖片過大或過多造成程式引入時呈現當機的假象。
2012/11/02 1:44補充:
由於先前誤解演算法,導致均化效果不佳,如今重新更改圖片以及新增老師的範例圖片處理,如下:
關於均化的演算法,首先統計出各個亮點的分佈,也就是直方圖,然後統計出各個亮點的累積圖,最後將原圖每個亮點依照累積圖所映射的數值做更改即可完成。
註:參照的映射為灰階直方圖,利用該直方圖去針對給個RGB做修改,因此均化後的圖片必定有許多點的成像被破壞,導致圖片看似出錯。
沒有留言:
張貼留言