之前影像處理課有寫過直方圖均化(Histogram Equalization)的程式,
這篇是重新紀錄做法,以及提供 Web 的演示。
因為最近稍微小忙,為了保持每月更新的步調,
所以挑了一個比較簡單的主題先寫這樣 XD”
請參閱 我的大學作業整理 的「影像處理課程」部分。
色階與直方圖
圖片的「色階」(level)是統計圖片像素的灰階亮度或各顏色分量,
然後依照其值與像素的數量,畫成一張直方圖(histogram)如圖 1 所示:
嚴格說,色階是顏色亮度的強弱,但直方圖是表示色階的一種圖表;
表示色階未必要用直方圖,而且直方圖的 X 與 Y 軸也不見得是亮度與數量。
直方圖均化
直觀地說,直方圖均化(histogram equalization)做法是紀錄圖像中,每個像素(pixel)的亮度(brightness),
然後根據「每個像素亮度的數量」重新分配亮度的過程,具體作法如下:
- 初始化直方圖 $h(c, v) = 0 \ \forall c, v$ 其中 $c \in \{0, 1, 2\}$ 為顏色分量,而 $v = [0, 255] \in N$ 為統計數量
- 遍歷所有像素,計算出直方圖 $h(c, v)$
- 根據直方圖 $h$ 算出累積分布函數(Cumulative Distribution Function, CDF)
其定義為 $CDF(c, v) = \sum_{i = 0}^{v} h(c, i)$ - 按 $CDF$ 比例,重新分配像素 $p(c)$ 顏色 $c$ 的亮度值,定義為:
$$
p_{new}(c) = round\left(\text{color_range} \cdot \frac{p_{old}(c) - CDF_{min}(c)}{\text{image_size} - CDF_{min}(c)}\right) \ \forall c
$$
其中,根據累積分布函數的定義,有 $CDF_{min}(c) = CDF(c, 0)$ 的關係,
而 $\text{color_range}$ 是該顏色 $c$ 的最大值、$\text{image_size}$ 的圖片像素總數(寬、高相乘),
另外就是 $round$ 函數實際上可以根據需要調整(常見的候選為 $floor(x)$ 及 $ceil(x)$ 函數)。
具體的程式如下:
1 | /* 直方圖初始化 */ |
關於讀取、顯示圖片,請參考 JavaScript 檔案處理 及 MDN ImageData 相關文章。
在 Paint.net 軟體中的「自動色階」功能,就是「直方圖均化」。
演示
重複執行多次直方圖均化時,由於浮點數經過 $round(x)$ 函數,
會導致直方圖有時候會有稍微差異(約 1 個亮度值),但是對於圖片來說,並不會造成視覺上的改變。