VB圖像處理,(六)圖像的亮度對比度調整

在圖像處理中,恐怕大家最熟悉的就是對於圖像的亮度和對比度調整了。
前面一定也有很多人寫過這樣的文章了,但是想把我的這個系列作一個完整的小結,我就再羅嗦一番了。
還是以24位色圖像爲例子,每種色彩都可以用0-255,一共256種深度來表示。
如果我們把它畫在一個二維座標上,正好是一條直線。
比如我們將像素的色深作爲橫座標,輸出色深作爲縱座標的畫,正好是一條經過原點(0,0)的45度斜線。
 如圖中直線A所表示的,角T爲45度,表示它的對比度正好爲1。
那麼很容易就可以寫出它的直線方程:Out = In * 1 ,係數1就是對比度的概念
如果把條直線加上一個偏移量變成B,那麼它的直線方程就成爲:Out = In * 1 + (ab)
偏移量(ab)就是亮度的增量。
只要有初中的代數知識就很容易看出它滿足一條直線方程:Y= A * X + B
但是,我們這裏要處理的情況稍微有些不同,在圖像處理中,對比度和亮度要分別對待。
不能因爲對比度的改變而改變亮度,因爲我們習慣上把灰色(127,127)這一點作爲中心點。
比如,我們加大了對比度,原來的直線A就變成如直線D所表示的,在改變了對比度的同時,也增加了亮度(ab),而我們心目中的變化應該是入直線C那樣。也就是說,我們把(127,127)這一點映射成了座標系的原點。
那麼我們就要把原來的直線公式修改成:Y=( X - 127 ) * A + B + 127。A表示對比度,B表示亮度增量。
我們驗證一下:只要亮度增量 B=0,無論怎麼改變對比度 A,該直線始終通過中心點(127,127),也就是說改變對比度的同時,亮度沒有改變。
由此,我們就可以推導出顏色的對比度亮度計算公式了:
NewRed = (OldRed -127 ) * A + 127+ B
NewGreen = (OldGreen -127 ) * A + 127+B
NewBlue = (OldBlue -127 ) * A + 127+B
現在你是否已經準備着手用這個公式來寫出你自己的亮度對比度子程序了呢?
慢着,再多做一步吧。我們是在遍程序,不是在做初中代數考試。這多出來的一步將使你的程序的執行效率更高一些。
我們把上面的公式再推導一下:
Y=( X - 127 ) * A + B + 127  =>  Y = X * A - 127 * A + 127+B      (1)
                                              令:B = B -127 * A +127       (2)
由上面(1),(2)兩步,得到一個新的公式:Y = X * A + B
咦?怎麼又變回來了??
是的公式的形式確實是變回來了,不過B所代表的東西已經不同了。
或許你又會說我這是多此一舉,請聰明的讀者想像一下:在一個普通的圖片做亮度對比度運算的時候,我們上面這些小小的變化將帶來什麼樣的效率提升。假設一張圖片大小是1027*768
一共有786432個像素,而每個像素又要分別計算紅綠藍三種顏色。
那麼,上述這個公式就需要計算786432 * 3 = 2359296 次,經過這麼多次運算的放大,哪怕是小小的一個重複計算都將浪費很長的時間。
因爲在調用子程序的時候亮度和對比度都已經確定,那麼B = B -127 * A +127這一步就可以放在循環的外面先作好。從而減少了程序的運算時間。
下面給出我的程序,以供參考: 
Public Sub BrightnessAndContrast(ByVal RedOffset As Long, ByVal GreenOffset As Long, ByVal BlueOffset As Long, Optional ByVal RedContrast As Single = 1, Optional ByVal GreenContrast As Single = 1, Optional ByVal BlueContrast As Single = 1)
Dim X As Long
Dim Y As Long
Dim MidR As Integer
Dim MidG As Integer
Dim MidB As Integer
Dim Max As Long

On Error GoTo ErrLine
Done = False
TimeFilter = timeGetTime
MidR = RedOffset - 127 * (RedContrast - 1)        '計算新的位移量B
MidG = GreenOffset - 127 * (GreenContrast - 1)
MidB = BlueOffset - 127 * (BlueContrast - 1)
Max = 255
For X = 0 To OutPutWid
   For Y = 0 To OutPutHei
      R = ColOut(2, X, Y)
      G = ColOut(1, X, Y)
      B = ColOut(0, X, Y)
      R = R * RedContrast + MidR      '計算Y = X * A + B
      G = G * GreenContrast + MidG
      B = B * BlueContrast + MidB
      If R > Max Then R = Max           '輸出值判斷是否在0到255之間
      If R < 0 Then R = 0
      If G > Max Then G = Max
      If G < 0 Then G = 0
      If B > Max Then B = Max
      If B < 0 Then B = 0
      ColOut(2, X, Y) = R
      ColOut(1, X, Y) = G
      ColOut(0, X, Y) = B
   Next
Next
Done = True
TimeFilter = timeGetTime - TimeFilter
Exit Sub
ErrLine:
MsgBox Err.Description
Done = True
End Sub

因爲在亮度對比度的過程中會出現計算值超出(0,255)的範圍,因此需要對它做一個判斷,把結果限定在這個範圍之內。
這個程序很簡單,可以根據給定的紅綠藍的亮度偏移量和對比度參數計算。由於把三種顏色的6個參數分開,也可以只調整單獨的一種顏色。
還有一個好處,就是當你將對比度參數設爲負值的時候,可以直接得到原圖片的反色輸出。(這也是將前面的座標系原點移動到127這一點的一個好處。)
下面是用我的程序處理得到的效果:
原圖:                            
亮度+20,對比度1.5效果:
對比度 -1,反相色彩效果:

作爲這個系列的最後一篇文章,我在我的程序ImageCast中所用到的所效果的算法和主要代碼都已經貼出來了。也算是對自己對大家的一個小小交待吧。
如果有興趣的朋友可以下載我的程序試試。
下載地址:http://download.csdn.net/source/325026

如果讀者對這個過程中的一些數組和變量不清楚,請參考我前面的幾篇文章,其中有詳細說明:

VB圖像處理,(一)像素的獲取和輸出

(這裏只是說了我自己在寫程序的時候用到的方法,存在很多的不足。並且因爲在貼上來的時候作了部分修改,可能會存在部分錯誤,請各位高手不吝賜教,將您用到的更好的方法提供一下,我將不勝感激。)

 

 

 

VB圖像處理,(二)二次線性插值的應用

VB圖像處理,(三)幾個常用濾鏡的實現1

VB圖像處理,(四)幾個常用濾鏡的實現2

VB圖像處理,(五)圖像的色彩糾正 
 

VB圖像處理,(六)圖像的亮度對比度調整

 

VB圖像處理,(七)一種鄰近均值濾波器的算法介紹(去塵,去噪音) (新增)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章