查看: 3673|回复: 3
打印 上一主题 下一主题

[经验分享] unity3d shader之Roberts,Sobel,Canny 三种边缘检测方法

[复制链接]

100

主题

3

听众

7683

积分

高级设计师

Rank: 6Rank: 6

纳金币
2378
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2015-2-11 21:24:04 |只看该作者 |倒序浏览

方法其实都差不多,就是用两个过滤器,分别处理两个分量

Sobel算子

先说Sobel算子

GX为水平过滤器,GY为垂直过滤器,垂直过滤器就是水平过滤器旋转90度。

过滤器为3x3的矩阵,将与图像作平面卷积。

如果不存在边则两个点颜色很接近,过滤器返回一个较小的值,否则就可判断出边缘的存在。

当前点为中间点


具体计算如下:

求出图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小



本shdaer将G值作为颜色输出

Roberts算子

Roberts算子与之相似

过滤器是2x2的矩阵

过滤器如下:

当前点为左上角的点

具体计算如下:


Canny算子

过滤器是2x2的矩阵

以sobel为例:

看看shader的实现

在frag函数中

float3 lum = float3(0.2125,0.7154,0.0721);

转化为luminance亮度值的变量


获取当前点的周围的点,并与luminance点积,求出亮度值(黑白图)

float mc00 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(1,1)/_Size).rgb, lum);

float mc10 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(0,1)/_Size).rgb, lum);

float mc20 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(-1,1)/_Size).rgb, lum);

。。。。。。。        

由于CG函数tex2DSize函数(获取图片长宽的像素数)在unity中不能用,我也不知道用什么函数来替代它,就弄了个外部变量_Size方便调节。

如果有什么函数能代替tex2DSize函数各位看官一定要告诉我。


根据过滤器矩阵求出GX水平和GY垂直的灰度值float GX = -1 * mc00 + mc20 + -2 * mc01 + 2 * mc21 - mc02 + mc22;

float GY = mc00 + 2 * mc10 + mc20 - mc02 - 2 * mc12 - mc22;

G = sqrt(GX*GX+GY*GY);

标准灰度公式

G = abs(GX)+abs(GY);


近似灰度公式

c = length(float2(GX,GY));

length的内部算法就是灰度公式的算法,欧几里得长度

float length(float3 v)

{

return sqrt(dot(v,v));

}

c即是最终输出



让我们看看效果:

可以看见对于这种简单的卡通,三种算法都非常清晰,sobel和roberts稍好一点。

再看看复杂一些的图片

Roberts的纹路非常清晰,有一些噪声

Sobel比Roberts还要清晰,噪声相对少些

canny已经没法看了,噪声太多,边缘判断的不清楚

综上,从结果来看,sobel算子的实现效果最好

下面给出sobel的shader:

Shader "Custom/sobel" {  Properties {    _MainTex ("MainTex", 2D) = "white" {}    _Size("Size", range(1,2048)) = 256//size      }  SubShader {    pass{    Tags{"LightMode"="ForwardBase" }    Cull off    CGPROGRAM    #pragma vertex vert    #pragma fragment frag    #include "UnityCG.cginc"    float _Size;    sampler2D _MainTex;    float4 _MainTex_ST;    struct v2f {      float4 pos:SV_POSITION;      float2 uv_MainTex:TEXCOORD0;          };    v2f vert (appdata_full v) {      v2f o;      o.pos=mul(UNITY_MATRIX_MVP,v.vertex);      o.uv_MainTex = TRANSFORM_TEX(v.texcoord,_MainTex);      return o;    }    float4 frag(v2f i):COLOR    {      float3 lum = float3(0.2125,0.7154,0.0721);//转化为luminance亮度值      //获取当前点的周围的点      //并与luminance点积,求出亮度值(黑白图)      float mc00 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(1,1)/_Size).rgb, lum);      float mc10 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(0,1)/_Size).rgb, lum);      float mc20 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(-1,1)/_Size).rgb, lum);      float mc01 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(1,0)/_Size).rgb, lum);      float mc11mc = dot(tex2D (_MainTex, i.uv_MainTex).rgb, lum);      float mc21 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(-1,0)/_Size).rgb, lum);      float mc02 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(1,-1)/_Size).rgb, lum);      float mc12 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(0,-1)/_Size).rgb, lum);      float mc22 = dot(tex2D (_MainTex, i.uv_MainTex-fixed2(-1,-1)/_Size).rgb, lum);      //根据过滤器矩阵求出GX水平和GY垂直的灰度值      float GX = -1 * mc00 + mc20 + -2 * mc01 + 2 * mc21 - mc02 + mc22;      float GY = mc00 + 2 * mc10 + mc20 - mc02 - 2 * mc12 - mc22;    //        float G = sqrt(GX*GX+GY*GY);//标准灰度公式      float G = abs(GX)+abs(GY);//近似灰度公式//                        float th = atan(GY/GX);//灰度方向      float4 c = 0;//                        c = G>th?1:0;//                        c = G/th*2;      c = length(float2(GX,GY));//length的内部算法就是灰度公式的算法,欧几里得长度      return c;    }    ENDCG    }//  } }

-----------------------by  wolf96



分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

10

主题

2

听众

1545

积分

助理设计师

Rank: 4

纳金币
79
精华
0

活跃会员

沙发
发表于 2015-2-12 09:41:54 |只看该作者
不错的文章,但是图片刷不出。。。。
回复

使用道具 举报

1

主题

1

听众

520

积分

初级设计师

Rank: 3Rank: 3

纳金币
14
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

板凳
发表于 2015-2-17 17:52:09 |只看该作者
谢谢分享
回复

使用道具 举报

1

主题

1

听众

987

积分

初级设计师

Rank: 3Rank: 3

纳金币
59
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2015-2-26 22:36:59 |只看该作者
看不到图
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-8-5 19:36 , Processed in 0.095627 second(s), 27 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部