Sobel Filter是一個(gè)相當(dāng)簡(jiǎn)單的邊緣查找算法,他能檢測(cè)比較銳利的邊緣(模糊的圖片或不銳利的邊緣無法有效檢測(cè),請(qǐng)搜索Canny Filter算法)
方法是獲得當(dāng)前點(diǎn)以及周圍點(diǎn)的權(quán)重來描述當(dāng)前點(diǎn)位置上的邊緣強(qiáng)度(顏色變化速度)
-
橫向邊緣檢測(cè)Mx
-
紫色像素的周圍九宮格與橫向檢測(cè)矩陣dot得到一個(gè)值,這個(gè)值的大小就是邊緣顏色變化率,當(dāng)兩側(cè)顏色相同或相近時(shí),你可以看到這個(gè)值趨近于0. 整體圖視作Gx
-
同樣方法可以檢測(cè)縱向的顏色變化,這樣可以得到一張圖片的兩個(gè)不同方向的灰度變化圖Gx和Gy
-
如何混合兩個(gè)不同方向上的邊緣強(qiáng)度變化?
答案是兩個(gè)方向的平方和開方
強(qiáng)度為G = (Gx*Gx+Gy*Gy)^0.5;
方向?yàn)?R = atan(Gy/Gx);
godot shader實(shí)現(xiàn)
- 這里只用到了強(qiáng)度
- 因?yàn)間dshader的內(nèi)建函數(shù)還不能在自定義函數(shù)中直接調(diào)用,暫時(shí)使用傳參方法
shader_type canvas_item;
vec3 samplef(vec2 offset, vec2 uv, sampler2D text, vec2 tsize){
return texture(text, vec2(uv+offset*tsize)).rgb;
}
float luminance(vec3 c){
return dot(c,vec3(.2126,.7152,.0722));
// return dot(c,vec3(1.))*0.3333;
}
vec3 sobelFilter(vec2 uv, sampler2D text, vec2 tsize){
//
vec3 hc=samplef(vec2(-1.,-1.),uv,text,tsize)+samplef(vec2(0.,-1.),uv,text,tsize)*2.
+samplef(vec2(1.,-1.),uv,text,tsize)+samplef(vec2(-1.,1.),uv,text,tsize)*-1.
+samplef(vec2(0.,1.),uv,text,tsize)*-2.+samplef(vec2(1.,1.),uv,text,tsize)*-1.;
//
vec3 vc=samplef(vec2(-1.,-1.),uv,text,tsize)+samplef(vec2(-1.,0.),uv,text,tsize)*2.
+samplef(vec2(-1.,1.),uv,text,tsize)+samplef(vec2(1.,-1.),uv,text,tsize)*-1.
+samplef(vec2(1.,0.),uv,text,tsize)*-2.+samplef(vec2(1.,1.),uv,text,tsize)*-1.;
return texture(text,uv).rgb*pow(luminance(vc*vc+hc*hc),.6);
}
void fragment(){
// COLOR = vec4(sobelFilter(UV, TEXTURE, TEXTURE_PIXEL_SIZE),1.0);
// COLOR = vec4(vec3(length(sobelFilter(UV,TEXTURE,TEXTURE_PIXEL_SIZE))),1.);
COLOR = vec4(vec3(length(sobelFilter(UV,TEXTURE,TEXTURE_PIXEL_SIZE))),texture(TEXTURE,UV).a);
}
| 原圖 | 結(jié)果 |
|---|---|
![]() | |
![]() | |
![]() | |
![]() |
視頻:
https://www.bilibili.com/video/av15346632?from=search&seid=17167334084508443686







