VB圖像處理之圖像的色彩糾正
前幾次為大家講述了如何通過操作像素來實現一些簡單的濾鏡效果。這次想更大家講述一下用灰度直方圖均衡來調整圖像的色彩空間。
先給大家介紹一下一些顏色的小常識。以電腦的顏色來說,顏色的組成是右紅、綠、藍三種顏色組成。以最容易的24位色來說,紅色、綠色、藍色各用1個字節來表示,1個字節有8位,所以加在一起正好是24位。由于電腦無法用連續的模擬值來表示一個自然量,只能將它們分成一段一段來顯示,分得越多就越接近自然。1個字節是2^8=256,所以在24位色中每一個單色都有256種不同的強度,三種顏色按照不同的強度混合,可以得到2^24種色彩。大約可以表達1677萬種色彩,對于人的眼睛來說已經和自然色彩沒有區別了。
如果我們用PHOTOSHOP來打開一張圖片,選擇LEVEL工具,就可以察看這張圖片的色彩分布了。
原圖:
灰度通道:
紅色通道:
綠色通道:
藍色通道:
由上面的四個通道圖,我們可以發現,這張圖片的色彩都是以低亮度為主,紅綠藍三色在高亮度區域的分布都很少,而灰度通道也表明整張圖片的亮度值很低。
在前面的文章中,我已經和大家講過,人眼對于灰度(亮度)的敏感程度最高。因此,如果我們能通過一種方法把這章圖片的灰度提高,那么它在我們的視覺中就會有更好的表現。
或許有朋友說只要把圖片加亮度,不是就可以了嗎?不錯,通過提高所有色彩的亮度,可以把原來處于第亮區域的色彩轉移到中亮度或高亮度區域,但是大家也知道,在算法中,加亮度只是很簡單的在R、G、B三個值后面直接加上一個偏移量: NewRed=OldRed+Offset,NewGreen=OldGreen+Offset,NewBlue+Offset,但是這種做法只是“粗暴”地將整個色彩空間搬了一個位置,而沒有改變其分布。請看下面,我在這張圖片加上了120點亮度:再看看此時的色彩分布你就知道我為什么說它“粗暴”了。
灰度通道:
紅色通道:
綠色通道:
藍色通道:
可以看到,原圖上的高亮度部分的色彩信息全部丟失,而低亮度部分(0-120)則是一片空白,如果說原來的圖片是2^8×2^8×2^8 一共1677萬色的話,那么現在的圖片則是:(256-120)^3=251萬色,也就是說,通過我們給圖片加了120點的亮度,我們丟失了一大半的顏色信息。
(選擇加120點亮度是為了使圖片的整體亮度和直方圖均衡后的亮度相當,易于比較。)
那么,有什么方法可以在不丟失,或丟失很少的顏色信息的前提下做到是圖片顯示更好呢?
有,這就是今天要說的“灰度直方圖均衡”的方法。
先給大家看一下效果:下面是將原來的圖片通過灰度直方圖的方法處理后的效果和前面的比較。
原圖:
提高亮度120:
灰度直方圖均衡:
通過直方圖均衡后的顏色分布如下:
灰度通道:
紅色通道:
綠色通道:
藍色通道:
通過對比,我們可以發現,灰度直方圖均衡,是對原圖中的色彩分布按照出現的頻率作了一個分布。
將出現最多的色彩“分”開,將出現很少的色彩“擠”得更緊,這樣作的好處就是把我們眼睛所看到的主體表示得更鮮明了。
好了,關于效果,也已經說得很多了,下面我們就來說明一下這個算法是如何實現的。
首先,我們需要獲取要處理的圖片中所有像素的色彩分布統計,也就是上面的幾個通道所作那樣。
假設有一張圖(我們直接用灰度來表示):
統計入下:
這張圖一共有9個像素,我們用比例來表示每種顏色的出現比例:
由于所有的色彩出現的次數不可能超過圖片的總像素,因此,將所有色彩的比例相加也不會超過1(大家已經可以看出正好是1)
最后我們按照從低到高的順序,把各個色彩的比例進行加權統計,也就是當前點的“權”等于該點的原有比例加上前一個點的“權”,我們得到一個新的統計表:
最后,根據這個新的統計表,我們來把像素的亮度用一個新的亮度來代替,算法為:
新亮度=該點“權”×255
這時我們得到了新的圖:
原圖中相對出現頻率多的部分的寬度變大了。而出現較少的部分則變窄了。
所以,灰度直方圖均衡的作用就是把一張圖片上出現多的色彩拓展,而把出現少的色彩壓縮。
從而得到了更“均衡”的色彩分布。
下面附上我的例程:
如果讀者對這個過程中的一些數組和變量不清楚,請參考我前面的幾篇文章,其中有詳細說明:
VB圖像處理之像素的獲取和輸出
VB圖像處理之二次線性插值的應用
VB圖像處理之幾個常用濾鏡的實現
VB圖像處理之鉛筆畫算法和木雕算法
下一篇將繼續為大家講述顏色對比度和亮度的調節算法,以及彩色圖片轉換到灰度圖片的算法。
不要以為這個很簡單,中間還是有一些小問題要注意的哦。
先給大家介紹一下一些顏色的小常識。以電腦的顏色來說,顏色的組成是右紅、綠、藍三種顏色組成。以最容易的24位色來說,紅色、綠色、藍色各用1個字節來表示,1個字節有8位,所以加在一起正好是24位。由于電腦無法用連續的模擬值來表示一個自然量,只能將它們分成一段一段來顯示,分得越多就越接近自然。1個字節是2^8=256,所以在24位色中每一個單色都有256種不同的強度,三種顏色按照不同的強度混合,可以得到2^24種色彩。大約可以表達1677萬種色彩,對于人的眼睛來說已經和自然色彩沒有區別了。
如果我們用PHOTOSHOP來打開一張圖片,選擇LEVEL工具,就可以察看這張圖片的色彩分布了。
原圖:
![]() |
灰度通道:
![]() |
紅色通道:
![]() |
綠色通道:
![]() |
藍色通道:
![]() |
由上面的四個通道圖,我們可以發現,這張圖片的色彩都是以低亮度為主,紅綠藍三色在高亮度區域的分布都很少,而灰度通道也表明整張圖片的亮度值很低。
在前面的文章中,我已經和大家講過,人眼對于灰度(亮度)的敏感程度最高。因此,如果我們能通過一種方法把這章圖片的灰度提高,那么它在我們的視覺中就會有更好的表現。
或許有朋友說只要把圖片加亮度,不是就可以了嗎?不錯,通過提高所有色彩的亮度,可以把原來處于第亮區域的色彩轉移到中亮度或高亮度區域,但是大家也知道,在算法中,加亮度只是很簡單的在R、G、B三個值后面直接加上一個偏移量: NewRed=OldRed+Offset,NewGreen=OldGreen+Offset,NewBlue+Offset,但是這種做法只是“粗暴”地將整個色彩空間搬了一個位置,而沒有改變其分布。請看下面,我在這張圖片加上了120點亮度:再看看此時的色彩分布你就知道我為什么說它“粗暴”了。
灰度通道:
![]() |
紅色通道:
![]() |
綠色通道:
![]() |
藍色通道:
![]() |
可以看到,原圖上的高亮度部分的色彩信息全部丟失,而低亮度部分(0-120)則是一片空白,如果說原來的圖片是2^8×2^8×2^8 一共1677萬色的話,那么現在的圖片則是:(256-120)^3=251萬色,也就是說,通過我們給圖片加了120點的亮度,我們丟失了一大半的顏色信息。
(選擇加120點亮度是為了使圖片的整體亮度和直方圖均衡后的亮度相當,易于比較。)
那么,有什么方法可以在不丟失,或丟失很少的顏色信息的前提下做到是圖片顯示更好呢?
有,這就是今天要說的“灰度直方圖均衡”的方法。
先給大家看一下效果:下面是將原來的圖片通過灰度直方圖的方法處理后的效果和前面的比較。
原圖:
![]() |
提高亮度120:
![]() |
灰度直方圖均衡:
![]() |
通過直方圖均衡后的顏色分布如下:
灰度通道:
![]() |
紅色通道:
![]() |
綠色通道:
![]() |
藍色通道:
![]() |
通過對比,我們可以發現,灰度直方圖均衡,是對原圖中的色彩分布按照出現的頻率作了一個分布。
將出現最多的色彩“分”開,將出現很少的色彩“擠”得更緊,這樣作的好處就是把我們眼睛所看到的主體表示得更鮮明了。
好了,關于效果,也已經說得很多了,下面我們就來說明一下這個算法是如何實現的。
首先,我們需要獲取要處理的圖片中所有像素的色彩分布統計,也就是上面的幾個通道所作那樣。
假設有一張圖(我們直接用灰度來表示):
| 100 50 20 20 40 50 100 250 200 |
統計入下:
| 20:2 40:1 50:2 100:2 200:1 250:1 |
這張圖一共有9個像素,我們用比例來表示每種顏色的出現比例:
| 20:2 / 9 40:1 / 9 50:2 / 9 100:2 / 9 200:1 / 9 250:1 / 9 |
由于所有的色彩出現的次數不可能超過圖片的總像素,因此,將所有色彩的比例相加也不會超過1(大家已經可以看出正好是1)
最后我們按照從低到高的順序,把各個色彩的比例進行加權統計,也就是當前點的“權”等于該點的原有比例加上前一個點的“權”,我們得到一個新的統計表:
| 20:2 / 9 40:3 / 9 50:5 / 9 100:7 / 9 200:8 / 9 250:9 / 9 |
最后,根據這個新的統計表,我們來把像素的亮度用一個新的亮度來代替,算法為:
新亮度=該點“權”×255
| 20:2 / 9 >> 20 (第一點不動,依然用20) 40:3 / 9×255=85 50:5 / 9×255=141 100:7 / 9×255=198 200:8 / 9×255=226 250:9 / 9×255=255 |
這時我們得到了新的圖:
| 100 50 20 198 141 20 20 40 50 >> 10 85 141 100 250 200 198 255 226 |
原圖中相對出現頻率多的部分的寬度變大了。而出現較少的部分則變窄了。
所以,灰度直方圖均衡的作用就是把一張圖片上出現多的色彩拓展,而把出現少的色彩壓縮。
從而得到了更“均衡”的色彩分布。
下面附上我的例程:
| Private Type ColorChart ColorCount(255) As Long '統計原來圖片中的亮度出現次數 PixcelCount As Long '記錄圖片的像素個數 ColRatio(255) As Single '記錄每一個亮度的出現比例 NewVal(255) As Byte '存放新的亮度索引 End Type Dim ColChart As ColorChart Public Sub StatisticsChart() Dim R As Byte Dim G As Byte Dim B As Byte Dim Gray As Integer Dim X As Long Dim Y As Long Dim I As Long Dim L As Long Dim M As Long Dim C As Double On Error GoTo ErrLine Done = False TimeFilter = timeGetTime With ColChart For X = 0 To 255 '先把數組清零 .ColorCount(X) = 0 Next For X = 0 To OutPutWid '這兩個循環用來掃描圖片數據,記錄每個點的灰度和出現次數 For Y = 0 To OutPutHei R = ColVal(2, X, Y) G = ColVal(1, X, Y) B = ColVal(0, X, Y) Gray = R * 3 + G * 6 + B Gray = Gray 10 .ColorCount(Gray) = .ColorCount(Gray) + 1 Next Next .PixcelCount = X * Y '獲得圖片的像素總量 C = 1 / .PixcelCount .ColRatio( 0) = .ColorCount(M, 0) * C '計算每個亮度的出現比例 .NewVal( 0) = 0 '色值最小的色彩總是為0,不參與計算 L = 0 For I = 1 To 255 .ColRatio(I) = .ColorCount( I) * C + .ColRatio( L) '進行加權 .NewVal(I) = .ColRatio( I) * 255 '計算新的顏色索引 L = L + 1 Next For X = 0 To OutPutWid For Y = 0 To OutPutHei R = Colval(2, X, Y) '讀取原來點的顏色 G = Colval(1, X, Y) B = Colval(0, X, Y) R = .NewVal( R) '查表得到新的顏色 G = .NewVal( G) B = .NewVal( B) ColOut(2, X, Y) = R '把新的顏色放到輸出數組中 ColOut(1, X, Y) = G ColOut(0, X, Y) = B Next Next End With Done = True TimeFilter = timeGetTime - TimeFilter Exit Sub ErrLine: Done = True MsgBox Err.Description End Sub |
如果讀者對這個過程中的一些數組和變量不清楚,請參考我前面的幾篇文章,其中有詳細說明:
VB圖像處理之像素的獲取和輸出
VB圖像處理之二次線性插值的應用
VB圖像處理之幾個常用濾鏡的實現
VB圖像處理之鉛筆畫算法和木雕算法
下一篇將繼續為大家講述顏色對比度和亮度的調節算法,以及彩色圖片轉換到灰度圖片的算法。
不要以為這個很簡單,中間還是有一些小問題要注意的哦。














