高斯模糊,见 百度百科

也使用卷积来实现,每个卷积元素的公式为:

其中б是标准方差,一般取值为1。

x和y分别对应当前位置到卷积中心的整数距离。

由于需要对高斯核中的权重进行归一化,即使所有权重相加为1,因此e前面的系数实际不会对结果产生任何影响。

转载请注明出处:http://www.cnblogs.com/jietian331/p/7238032.html

综上,公式简化为:

G(x,y) = e-(x*x+y*y)/2

因此,高斯核计算代码如下:

 using System;

 namespace TestShell
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("输入需要得到的高斯卷积核的维数(如3,5,7...):"); string input = Console.ReadLine();
int size; if (!int.TryParse(input, out size))
{
Console.WriteLine("不是数字...");
return;
} // 计算
double[] r2 = null;
double[,] r = null;
try
{
r = CalcGaussianBlur(size, out r2);
}
catch (Exception ex)
{
Console.WriteLine("错误: " + ex.Message);
} if (r != null && r2 != null)
{
// 卷积如下:
Console.WriteLine();
Console.WriteLine("{0}x{0}的高斯卷积核如下:", size);
for (int i = ; i < r.GetLongLength(); i++)
{
for (int j = ; j < r.GetLongLength(); j++)
{
Console.Write("{0:f4}\t", r[i, j]);
}
Console.WriteLine();
}
Console.WriteLine(); Console.WriteLine("可拆成2个一维的数组:");
for (int i = ; i < r2.Length; i++)
{
Console.Write("{0:f4}\t", r2[i]);
}
Console.WriteLine();
Console.WriteLine(); Console.WriteLine("验证,使用这2个一维的数组也可以得到同样的结果:");
for (int i = ; i < size; i++)
{
for (int j = ; j < size; j++)
{
Console.Write("{0:f4}\t", r2[i] * r2[j]); }
Console.WriteLine();
}
} Console.WriteLine();
Console.WriteLine("按任意键结束...");
Console.ReadKey();
} static double[,] CalcGaussianBlur(int size, out double[] r2)
{
if (size < )
throw new ArgumentException("size < 3");
if (size % != )
throw new ArgumentException("size % 2 != 1"); double[,] r = new double[size, size];
r2 = new double[size];
int center = (int)Math.Floor(size / 2f);
double sum = ; for (int i = ; i < size; i++)
{
for (int j = ; j < size; j++)
{
int x = Math.Abs(i - center);
int y = Math.Abs(j - center);
double d = CalcItem(x, y);
r[i, j] = d;
sum += d;
}
} for (int i = ; i < size; i++)
{
for (int j = ; j < size; j++)
{
r[i, j] /= sum;
if (i == j)
r2[i] = Math.Sqrt(r[i, i]);
}
} return r;
} static double CalcItem(int x, int y)
{
return Math.Pow(Math.E, -(x * x + y * y) / 2d);
}
}
}

工具在:http://files.cnblogs.com/files/jietian331/CalcGaussianBlur.zip

一个5 x 5的高斯核如下:

使用2个一维数组可简化计算量,提高性能,通过观察可知,只需要计3个数:

使用unity shader屏幕后期处理来实现高斯模糊,代码如下。

子类:

 using UnityEngine;

 public class GaussianBlurRenderer : PostEffectRenderer
{
[Range(, )]
[SerializeField]
public int m_downSample = ; // 降采样率
[Range(, )]
[SerializeField]
public int m_iterations = ; // 迭代次数
[Range(0.2f, 3f)]
[SerializeField]
public float m_blurSpread = 0.6f; // 模糊扩散量 protected override void OnRenderImage(RenderTexture src, RenderTexture dest)
{
int w = (int)(src.width / m_downSample);
int h = (int)(src.height / m_downSample);
RenderTexture buffer0 = RenderTexture.GetTemporary(w, h);
RenderTexture buffer1 = RenderTexture.GetTemporary(w, h);
buffer0.filterMode = FilterMode.Bilinear;
buffer1.filterMode = FilterMode.Bilinear;
Graphics.Blit(src, buffer0); for (int i = ; i < m_iterations; i++)
{
Mat.SetFloat("_BlurSpread", + i * m_blurSpread); Graphics.Blit(buffer0, buffer1, Mat, );
Graphics.Blit(buffer1, buffer0, Mat, );
} Graphics.Blit(buffer0, dest);
RenderTexture.ReleaseTemporary(buffer0);
RenderTexture.ReleaseTemporary(buffer1);
} protected override string ShaderName
{
get { return "Custom/Gaussian Blur"; }
}
}

GaussianBlurRenderer

shader:

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Gaussian Blur"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
_BlurSpread("Blur Spread", float) =
} SubShader
{
CGINCLUDE sampler2D _MainTex;
float4 _MainTex_TexelSize;
uniform float _BlurSpread; struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
}; struct v2f
{
float4 pos : SV_POSITION;
float2 uv[] : TEXCOORD0;
}; v2f vertHorizontal(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float tsx = _MainTex_TexelSize.x * _BlurSpread;
o.uv[] = v.uv + float2(tsx * -, );
o.uv[] = v.uv + float2(tsx * -, );
o.uv[] = v.uv;
o.uv[] = v.uv + float2(tsx * , );
o.uv[] = v.uv + float2(tsx * , );
return o;
} v2f vertVertical(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
float tsy = _MainTex_TexelSize.y * _BlurSpread;
o.uv[] = v.uv + float2(, tsy * -);
o.uv[] = v.uv + float2(, tsy * -);
o.uv[] = v.uv;
o.uv[] = v.uv + float2(, tsy * );
o.uv[] = v.uv + float2(, tsy * );
return o;
} fixed4 frag(v2f i) : SV_TARGET
{
float g[] = {0.0545, 0.2442, 0.4026};
fixed4 col = tex2D(_MainTex, i.uv[]) * g[];
for(int k = ; k < ; k++)
{
col += tex2D(_MainTex, i.uv[k]) * g[k];
col += tex2D(_MainTex, i.uv[ - k]) * g[k];
}
return col;
} ENDCG Pass
{
Name "HORIZONTAL"
ZTest Always
ZWrite Off
Cull Off CGPROGRAM
#pragma vertex vertHorizontal
#pragma fragment frag
ENDCG
} Pass
{
Name "VERTICAL"
ZTest Always
ZWrite Off
Cull Off CGPROGRAM
#pragma vertex vertVertical
#pragma fragment frag
ENDCG
}
} Fallback Off
}

Custom/Gaussian Blur

调整参数:

DownSample,即降采样率,越大性能越好,图像越模糊,但过大可能会使图像像素化。

Iteraitions, 即迭代次数,越大图像模糊效果越好,但性能也会下降。

BlurSpread,即模糊扩散量,越大图像越模糊,但过大会造成虚影。

效果如下:

 

Unity shader学习之屏幕后期处理效果之高斯模糊的更多相关文章

  1. Unity shader学习之屏幕后期处理效果之Bloom效果

    Bloom特效是游戏中常见的一种屏幕效果.这种特效可以模拟真实摄像机的一种图像效果,它让画面中较亮的区域“扩散”到周围的区域中,造成一种朦胧的效果. Bloom的实现原理很简单,首先根据一个阈值提取出 ...

  2. Unity shader学习之屏幕后期处理效果之运动模糊

    运动模糊,代码如下: using UnityEngine; public class MotionBlurRenderer : PostEffectRenderer { [Range(0.1f, 0. ...

  3. Unity shader学习之屏幕后期处理效果之均值模糊

    均值模糊,也使用卷积来实现,之不过卷积中每个值均相等,且相加等于1. 代码如下, 子类: using UnityEngine; public class MeanBlurRenderer : Post ...

  4. Unity shader学习之屏幕后期处理效果之边缘检测

    边缘检测的原理是利用一些边缘检测算子对图像进行卷积操作. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7232707.html 例如: 代码如下: usin ...

  5. Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法2

    这里使用一种更高效地从深度纹理中重建世界坐标的方法. 首先计算摄像机的视锥体的四条射线向量进行线性插值,插值后的值便是该像素在世界空间坐标下到摄像机的方向. 然后通过与深度值相乘即可得到摄像机位置到该 ...

  6. Unity shader学习之屏幕后期效果之调整屏幕亮度,饱和度,对比度

    Unity的屏幕后期处理效果,使用MonoBehaviour.OnRenderImage来实现. 转载请注明出处:http://www.cnblogs.com/jietian331/p/7228063 ...

  7. Unity Shader 学习之旅

    Unity Shader 学习之旅 unityshader图形图像 纸上学来终觉浅,绝知此事要躬行 美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉 一.渲染流水线 示例图 Tips:什么是 GP ...

  8. Unity Shader 学习之旅之SurfaceShader

    Unity Shader 学习之旅之SurfaceShader unity shader 图形图像  如果大地的每个角落都充满了光明 谁还需要星星,谁还会 在夜里凝望 寻找遥远的安慰——江河 官方文档 ...

  9. 第四章 开始Unity Shader学习之旅(3)

    1. 程序员的烦恼:Debug 调试(debug),大概是所有程序员的噩梦.而不幸的是,对一个Shader进行调试更是噩梦中的噩梦.这也是造成Shader难写的原因之一--如果发现得到的效果不对,我们 ...

随机推荐

  1. 2016年蓝桥杯省赛A组c++第5题(计算机组成原理)

    /* 下面的代码把一个整数的二进制表示的最右边的连续的1全部变成0 如果最后一位是0,则原数字保持不变. 如果采用代码中的测试数据,应该输出: 0000000000000000000000000110 ...

  2. iOS-静态库,动态库,framework浅析(二)

    创建.a静态库 第一步,新建工程.     一般使用工程名就使用库的名称,比如我这里用FMDB来创建静态库,我的工程名就取名为FMDB,创建的.a静态库就是libFMDB.a.             ...

  3. 如何使用Beyond Compare 对比差异文件【制作Patch(补丁包)文件】

    场景:研发部的代码从SVN变更至GIt,通过Jenkins每天自动生成程序包. 如需要获取单独的程序包更新,而不是整个程序包覆盖更新,这时候就需要用到Beyond Compare 对比工具 操作步骤1 ...

  4. spring学习(01)之IOC

    spring学习(01)之IOC IOC:控制反转——Spring通过一种称作控制反转(IOC)的技术促进了低耦合.当应用了IOC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创 ...

  5. 【JMeter】【性能测试】响应信息不明确的接口做关联

    1:做接口关联的时候,发现接口响应没有可以利用的信息.如下图只返回了一个成功的标识,这样的接口如何与之关联? 通过抓包观察后续的修改功能,发现需要传入一个id和一个title.但是前面的接口没有返回, ...

  6. 【SQL】如何使用SQL like 方法和SQL [charlist] 通配符(SQL like的拓展)

    1.like 相关用法 '%a'    //以a结尾的数据 'a%'    //以a开头的数据 '%a%'    //含有a的数据 ‘_a_’    //三位且中间字母是a的 '_a'    //两位 ...

  7. 数据库——MongoDB

    what's the MongoDB MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bson格式 ...

  8. NYOJ 布线问题

    #include<iostream> #include<stdio.h> #include<queue> #include<algorithm> usi ...

  9. python连接redis

    一.首先,要下载redis pip3 install redis 二.连接redis import redis #拿到一个redis的链接 conn=redis.Redis('127.0.0.1',6 ...

  10. 万恶之源 - Python生成器

    生成器 首先我们来看看什么是个生成器,生成器本质就是迭代器 在python中有三种方式来获取生成器 1.通过生成器函数 2.通过各种推到式来实现生成器 3.通过数据的转换也可以获取生成器 首先,我们先 ...