zoukankan      html  css  js  c++  java
  • unity3d shader之Roberts,Sobel,Canny 三种边缘检测方法

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

    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  

  • 相关阅读:
    linux 下安装web开发环境
    js 字符串的操作
    css 弹出层-透明层
    Nginx服务器 之反向代理与负载均衡
    html5 响应式布局
    css 文本溢出显示省略号
    栈的运用(6)
    ctypes to load library in c/c++
    Expert Python programming
    Python type class metaclass
  • 原文地址:https://www.cnblogs.com/zhanlang96/p/4285244.html
Copyright © 2011-2022 走看看