【opencv】20.直方图均衡化的数学原理
本文只講數字圖像處理,即離散化后的公式,至于積分形式的分析,網上很多。
具體的數學推導可以參考這篇博客直方圖均衡化。
如果想自己代碼實現直方圖均衡化,相關源代碼可以參考(不使用api)使用C++實現彩色圖像直方圖均衡化的三種方法。
如果要直接使用opencv的api,直接一個函數搞定,用法如下:
在實際均衡化過程中,核心步驟如下:
說明:xix_ixi?是灰度值,取值[0~255],iii也取值為[0~255],xxx是一個像素(原始的),f(x)f(x)f(x)是直方圖均衡化之后的值。
- 1.計算灰度圖的直方圖;
- 2.遍歷灰度直方圖,對灰度值從 0~255 累計求和(圖像計算中,積分可以用求和來近似替代),對求和結果除以圖像的像素總數,然后乘以 L?1\color{red}L-1L?1得到函數結果 得到函數結果 f(xi)f(x_i)f(xi?)。
f(xi)=(L?1)∑0xih(xi)w?h\color{red}f(x_i)=(L-1)\sum_{0}^{x_i} {\frac{h(x_i)}{w*h}}f(xi?)=(L?1)0∑xi??w?hh(xi?)?
如果寫成迭代的式子,就是下面這樣:
f(xi)=f(xi?1)+(L?1)h(xi)w?h=(L?1)∑0xi?1h(xi?1)w?h+(L?1)h(xi)w?h\color{red} \begin{aligned} f(x_i) &= f(x_{i-1})+(L-1)\frac{h(x_{i})}{w*h} \\ &=(L-1)\sum_{0}^{x_{i-1}} {\frac{h(x_{i-1})}{w*h}}+(L-1)\frac{h(x_{i})}{w*h} \\ \end{aligned} f(xi?)?=f(xi?1?)+(L?1)w?hh(xi?)?=(L?1)0∑xi?1??w?hh(xi?1?)?+(L?1)w?hh(xi?)??
不過這種方式會產生小數,然后又取整,每次像素值都取整,有精度損失,雖然影響不大,但是更好的方式是對該像素和該像素之前的像素數量求和,count+=h(xi)count+=h(x_i)count+=h(xi?),
f(xi)=(L?1)countw?h\color{red}f(x_i)=(L-1)\frac{count}{w*h}f(xi?)=(L?1)w?hcount?
這個公式就是,當xi=80x_i=80xi?=80 時,灰度值為80的像素在直方圖均衡化之后的灰度值為f(xi)\color{red}f(x_i)f(xi?)。 - 3.將每一個灰度值累積求和的結果f(xi)f(x_i)f(xi?)存儲在一個大小為 256 的int數組中,存儲的位置為 iii;
- 4.遍歷輸入圖像每一個像素,記點值為xxx,修改其像素值使等于f(x)f(x)f(x)。
- 5.均衡化結束。
例子:
假設一幅圖中的像素范圍是 [10~160],有100個像素取值(因為有些像素值可能并沒有,例如,一張圖中像素值為75的像素一個都沒有),直方圖均衡化的做法就是:
其實累計求和就是下面這樣,假設灰度圖片總共有total=2550個像素:
| num | 0 | 0 | 0 | 250 | 500 | 10 | 800 | … | 100 | 0 | 0 |
| calculate: vnext=vpre+255?numtotalv_{next}=v_{pre}+255* \frac{num}{total}vnext?=vpre?+255?totalnum? 例:v10=v9+255?2502550v_{10}=v_{9}+255* \frac{250}{2550}v10?=v9?+255?2550250?, v255=v254+255?02550v_{255}=v_{254}+255* \frac{0}{2550}v255?=v254?+255?25500? | v0=0v_0=0v0?=0 | v1=v0+0v_1=v_0+0v1?=v0?+0 | 0 | v10=v9+255?2502550v_{10}=v_{9}+255* \frac{250}{2550}v10?=v9?+255?2550250? | v11 | v12 | v13 | v160 | v255 | ||
| final_pixel_value | 0 | 0 | 0 | 25 | 75 | 76 | 156 | 255 | 255 | 255 |
由上表可知,本來像素范圍在[10~160],直方圖均衡化之后,像素范圍變為了[25~255],動態范圍大大增加;
- 原來的低亮度像素值為10的變為了25,11的變為了75,12的變為了76, 13變為了156,160變成了255。可以看出該像素對應的灰度值在整幅圖中的個數越多,變換后的灰度值就越大。
- 本來像素12和像素13只相差1,直方圖均衡化之后,變為了76和156,對比度顯著變大,之所以會這樣,就是因為像素13比像素12的灰度值個數多,并且多的不是一個量級。
- 但是由于直方圖均衡化是遞增的,對于原來像素11和像素12只相差1,直方圖均衡化之后,變為了75和76,所以即使二者像素個數相差幾百個,對比度也沒有增大。
- 因此灰度值更高時,而像素數量驟減的話,并不會拉升對比度。只對灰度值更高,像素數量陡增時,才會拉升對比度。
假設該圖像有total=25500個像素,即像素個數擴大了10倍,本例把像素值為160的像素增大到了3000個:
| num | 0 | 0 | 0 | 250 | 500 | 10 | 800 | … | 3000 | 0 | 0 |
| calculate: vnext=vpre+255?numtotalv_{next}=v_{pre}+255* \frac{num}{total}vnext?=vpre?+255?totalnum? 例:v10=v9+255?25025500v_{10}=v_{9}+255* \frac{250}{25500}v10?=v9?+255?25500250?, v255=v254+255?025500v_{255}=v_{254}+255* \frac{0}{25500}v255?=v254?+255?255000? | v0=0v_0=0v0?=0 | v1=v0+0v_1=v_0+0v1?=v0?+0 | 0 | v10=v9+255?25025500v_{10}=v_{9}+255* \frac{250}{25500}v10?=v9?+255?25500250? | v11 | v12 | v13 | v160 | v255 | ||
| calculate_pixel_value | 0 | 0 | 0 | 2.5 | 7.5 | 7.6 | 15.6 | 255 | 255 | 255 | |
| final_pixel_value | 0 | 0 | 0 | 3 | 8 | 8 | 16 | 255 | 255 | 255 |
由上表可知,本來像素范圍在 [10~160],直方圖均衡化之后,像素范圍變為了 [3~255],動態范圍大大增加;
原來的低亮度像素值為10的變為了3,11的變為了85,12的變為了8, 13變為了16,160變成了255。可以看出該像素對應的灰度值在整幅圖中的個數越多,變換后的灰度值就越大。
圖像中像素灰度值數量最多的變亮了,那么整幅圖看起來就更亮,對比度更高,更清晰了。
總結
以上是生活随笔為你收集整理的【opencv】20.直方图均衡化的数学原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux】41. grep结合awk
- 下一篇: 【数学与算法】如何通俗的理解概率密度函数