高斯模糊,见 百度百科

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

其中б是标准方差,一般取值为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. shell 文件描述符

    /tmp/test.sh > /tmp/test.log 2>&1 这个命令的意思是 前半部分是将shell的输出重定向到/tmp/test/log.默认是标准输出(stdout文 ...

  2. [Day1]常用Dos命令,Java相关描述及基础

    1.常用的DOS命令 (1)返回上一级目录:cd.. (2)返回盘符根目录:cd\ (3)切换当前盘符:   盘符: (4)进入文件夹:       cd 文件路径 (5)展示当前目录下的所有内容:D ...

  3. Xcode 编辑器之Workspace,Project,Scheme,Target

    一,前言 最近老是突然对Workspace,Project,Scheme,Target四者的关系有些疑惑,所以查阅资料总结一下. 二,Workspace,Project,Scheme,Target四者 ...

  4. [git] 关闭 git branch 的pager

    高版本的git做了pager的调整. git diff git log git branch 等命令都用了pager, 默认的pager用了less 在我的应用里, 通常branch只有那么3,5个. ...

  5. [ovs] openvswitch 入门

    https://www.sdnlab.com/sdn-guide/14747.html http://sdnhub.cn/index.php/openv-switch-full-guide/ http ...

  6. odoo 权限设置

    *权限管理的四个层次    # 菜单级别:不属于指定菜单所包含组的用户看不到该菜单,不客全,只是隐藏                 菜单,若知道菜单ID,仍然可以通过指定URL访问    # 对象级 ...

  7. LeetCode 427 Construct Quad Tree 解题报告

    题目要求 We want to use quad trees to store an N x N boolean grid. Each cell in the grid can only be tru ...

  8. 20165336 2017-2018-2 《Java程序设计》第7周学习总结

    20165336 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 查询操作:向数据库发送SQL查询语句,处理查询结果,关闭连接. 顺序查询:next()方法向 ...

  9. 递归、嵌套for循环、map集合方式实现树形结构菜单列表查询

    有时候, 我们需要用到菜单列表,但是怎么样去实现一个菜单列表的编写呢,这是一重要的问题. 比如我们需要编写一个树形结构的菜单,那么我们可以使用JQuery的zTree插件:http://www.tre ...

  10. 003-hive安装

    http://www.aboutyun.com/thread-6902-1-1.html http://www.aboutyun.com/thread-7374-1-1.html