免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
Board logo

標題: VB圖像處理,(三)幾個常用濾鏡的實現1 [打印本頁]

作者: mhfo    時間: 2013-4-23 17:12     標題: VB圖像處理,(三)幾個常用濾鏡的實現1

http://big5.webasp.net/article/16/15905.htm

前面講到了二次線性插值的應用。
這一篇來給大家講一下關於銳化、柔化、擴散、雕刻這幾個濾鏡的實現。

一,銳化

銳化的算法很簡單,就是比較相鄰的幾個像素,把當前像素加上和周圍的像素的差就可以了。
這裡我給出一個示例:
A B C D
E F G H
I J K L
M N O P
假設有一個圖片,4*4,共16個像素,分別用A--L來代表。
我們先觀察這個圖片,只有中間的F,G,J,K這四個像素的「鄰居」是全的。


為了簡便起見,我們只處理這4個像素,因為在實際的圖片中由於圖片的大小都很多像素組成,所以周圍的一圈像素不做處理不會影響到最終的效果。
先計算差值: Delta= F - (A+B+C+E+G+I+J+K) / 8
(A+B+C+E+G+I+J+K) / 8就是F周圍的像素的平均值,
將這個平均值乘以一個係數再加到F上,就得到了一個新的F值:
F=F + Delta * Alpha
這個係數Alpha就是銳化度,改變這個係數就能得到不同的銳化效果。不過一般都是取得比較小的,如:0.3
於是,我們只要使用兩個循環來遍歷整個圖片的像素值(去除邊界)就能得到一個銳化的效果了。


但是大家或許會發現在處理後面幾個點的時候,前面的點的值已經不是原來的值了,
比如處理G的時候,需要用到F的值,而F則已經被改變,並且F的改變又和G的值有關係,這樣就會變成一種循環引用。為了避免整個問題,這裡給出一個改良的方法:
A B C D
E F G H
I J K L
M N O P
我們從A點開始做,將差值計算方法改成:
Delta= A - (B+E+F) / 3
F=F + Delta * Alpha
按照從左到右,從上到下的順序來掃瞄所有像素,這時在計算中就不會遇到已經被處理過的像素了,並且因為減少了參與運算的像素,整個處理過程也得以加快。

按照我們在VB圖像處理,(一)像素的獲取和輸出中已經得到的像素數組。我們可以這樣寫:
Public Sub Sharp(Optional ByVal SharpDgree As Single = 0.3)
Dim X As Long
Dim Y As Long
Dim Ix As Long
Dim Iy As Long
Dim Diff As Long
Dim Diff1 As Long
Dim Div1 As Single
Dim Div2 As Single
Dim Max As Long
On Error GoTo ErrLine

Max = 255
Done = False
TimeFilter = timeGetTime
TemplateSize = 1
Sensitivity = Sensitivity * 9
Div1 = 1 + SharpDgree
Div2 = -SharpDgree / 3
For X = 0 To OutPutWid - 1
For Y = 0 To OutPutHei -1
RR = ColOut(0, X, Y) * Div1
GG = ColOut(1, X, Y) * Div1
BB = ColOut(2, X, Y) * Div1
Ix = X + 1
Iy = Y + 1
R = ColOut(0, Ix, Iy)
R = R + ColOut(0, X, Iy) + ColOut(0, Ix, Y)
G = ColOut(1, Ix, Iy)
G = G + ColOut(1, X, Iy) + ColOut(1, Ix, Y)
B = ColOut(2, Ix, Iy)
B = B + ColOut(2, X, Iy) + ColOut(2, Ix, Y)
R = R * Div2
G = G * Div2
B = B * Div2
RR = RR + R
GG = GG + G
BB = BB + B
If RR < 0 Then RR = 0
If RR > Max Then RR = Max
If GG < 0 Then GG = 0
If GG > Max Then GG = Max
If BB < 0 Then BB = 0
If BB > Max Then BB = Max
ColOut(0, X, Y) = RR
ColOut(1, X, Y) = GG
ColOut(2, X, Y) = BB
Next
Next

Done = True
TimeFilter = timeGetTime - TimeFilter
Exit Sub
ErrLine:
Done = True
MsgBox Err.Description
End Sub

因為在計算新的像素的過程中會出現新的值大於255或小於0的情況,因此必須在計算完成後判斷。

所用到的全局變量:
Public TimeFilter As Long '用於記錄濾鏡處理所花費的時間
Dim RR As Long '用於保存紅色份量
Dim GG As Long '用於保存綠色份量
Dim BB As Long '用於保存藍色份量

二,柔化

柔化的算法和銳化相近似,不過作用正好相反,就是把當前點用周圍幾個點的平均值來代替。
A B C D
E F G H
I J K L
M N O P
計算方法:
F=(A+B+C+E+F+G+I+J+K) / 9
G=(B+C+D+F+G+H+J+K+L) / 9
...
...
具體的程序,我這裡就不囉嗦了,大家只要把上面的程序小小改動一下就可以了。

三,擴散,產生一種類似水彩畫的效果。
算法很簡單,就是將當前點用周圍的隨即的點來代替。
A B C D
E F G H
I J K L
M N O P
F點可以從它周圍的A,B,C,E,G,I,J,K中任意選一點代替。
G點可以從它周圍的B,C,D,F,H,J,K,L中任意選一點代替。
J點可以從它周圍的E,F,G,I,K,M,N,O中任意選一點代替。
K點可以從它周圍的F,G,H,J,L,N,O,P中任意選一點代替。
至於選哪一點,可以用一個隨即數來選定。

四,雕刻
將相鄰的兩個像素相減,得到的差加上127作為新的值
A B C D
E F G H
I J K L
M N O P
如果我們按照從左向右的方向來「雕刻」
A=B-A+127
B=C-B+127
C=D-C+127
...
如果我們按照從上向下的方向來「雕刻」
A=E-A+127
B=F-B+127
C=G-C+127
...
當然我們還可以從更多的方向來「雕刻」比如:向左下、右上、左上、右下...等等,一共8個可以選擇的方向。
另外這個127,就是「雕刻」效果後的亮度。我們可以把雕刻方向和亮度都作為參數寫到過程中
Public Sub Emboss(Optional EmbossDirection As Integer , Optional Lighteness As Integer)
...

這幾個濾鏡的算法都比較簡單,很容易用VB來實現。


鑒於篇幅的關係這次就講到這裡,下次和大家講鉛筆畫和木雕的效果。請大家繼續關注
前兩期內容請參考:
《VB圖像處理,(一)像素的獲取和輸出 》
《VB圖像處理,(二)二次線性插值的應用》

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




歡迎光臨 魚骨頭的雲端圖書館 (http://mhfo.hotbbs.info/) Powered by Discuz! 7.0.0