前面講到了二次線性插值的應用。這一篇來給大家講一下關於銳化、柔化、擴散、雕刻這幾個濾鏡的實現。
一、銳化 銳化的算法很簡單,就是比較相鄰的幾個像素,把當前像素加上和周圍的像素的差就可以了。這裡我給出一個示例:
->ABCD
EFGH
IJKL
MNOP->
假設有一個圖片,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的值有關系,這樣就會變成一種循環引用。為了避免整個問題,這裡給出一個改良的方法:
->ABCD
EFGH
IJKL
MNOP->
我們從A點開始做,將差值計算方法改成:
->Delta=A-(B E F)/3
F=F Delta*Alpha->
按照從左到右,從上到下的順序來掃描所有像素,這時在計算中就不會遇到已經被處理過的像素了,並且因為減少了參與運算的像素,整個處理過程也得以加快。
按照我們在《VB圖像處理之像素的獲取和輸出》中已經得到的像素數組。我們可以這樣寫:
->PublicSubSharp(OptionalByValSharpDgreeAsSingle=0.3)
DimXAsLong
DimYAsLong
DimIxAsLong
DimIyAsLong
DimDiffAsLong
DimDiff1AsLong
DimDiv1AsSingle
DimDiv2AsSingle
DimMaxAsLong
OnErrorGoToErrLine
Max=255
Done=False
TimeFilter=timeGetTime
TemplateSize=1
Sensitivity=Sensitivity*9
Div1=1 SharpDgree
Div2=-SharpDgree/3
ForX=0ToOutPutWid-1
ForY=0ToOutPutHei-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
IfRR<0ThenRR=0
IfRR>MaxThenRR=Max
IfGG<0ThenGG=0
IfGG>MaxThenGG=Max
IfBB<0ThenBB=0
IfBB>MaxThenBB=Max
ColOut(0,X,Y)=RR
ColOut(1,X,Y)=GG
ColOut(2,X,Y)=BB
Next
Next
Done=True
TimeFilter=timeGetTime-TimeFilter
ExitSub
ErrLine:
Done=True
MsgBoxErr.Description
EndSub->
因為在計算新的像素的過程中會出現新的值大於255或小於0的情況,因此必須在計算完成後判斷。
所用到的全局變量:
->PublicTimeFilterAsLong'用於記錄濾鏡處理所花費的時間
DimRRAsLong'用於保存紅色分量
DimGGAsLong'用於保存綠色分量
DimBBAsLong'用於保存藍色分量->
原圖:
->
->
銳化效果:
->->
->二、柔化
柔化的算法和銳化相近似,不過作用正好相反,就是把當前點用周圍幾個點的平均值來代替。
->ABCD
EFGH
IJKL
MNOP->
計算方法:
->F=(A B C E F G I J K)/9
G=(B C D F G H J K L)/9
...
...->
具體的程序,我這裡就不羅嗦了,大家只要把上面的程序小小改動一下就可以了。
原圖:
->->
柔化效果:
->->
三、擴散
產生一種類似水彩畫的效果。
算法很簡單,就是將當前點用周圍的隨即的點來代替。
->ABCD
EFGH
IJKL
MNOP->
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作為新的值
->ABCD
EFGH
IJKL
MNOP->
如果我們按照從左向右的方向來“雕刻”
->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,就是“雕刻”效果後的亮度。我們可以把雕刻方向和亮度都作為參數寫到過程中
->PublicSubEmboss(OptionalEmbossDirectionAsInteger,OptionalLightenessAsInteger)
...->
原圖:
->->
柔化效果:
->->
這幾個濾鏡的算法都比較簡單,很容易用VB來實現。->->