如何为1D高斯滤波器计算正态分布核?C#实现求助
Unity C#实现1D高斯滤波器平滑浮点列表
要把你的简单平均改成高斯滤波,核心是用正态分布权重替代等权重,需要做以下几处关键修改:
1. 预计算高斯核权重
高斯核的每个权重由1D正态分布公式计算:权重 = e^(-(x²)/(2σ²))
其中x是当前位置相对于核中心的距离(比如核宽度为5时,中心是0,左右分别是-2、-1、1、2),σ(西格玛)控制权重的集中程度,通常可以设为σ = 核宽度 / 6(因为正态分布99.7%的概率落在±3σ范围内,刚好覆盖整个核的宽度)。
2. 替换加权求和逻辑
原来的直接累加邻域值,改成邻域值乘以对应核权重后累加,最后用权重总和而非核宽度做归一化(避免边界截断时权重和变化导致的偏差)。
修改后的完整代码
using System.Collections.Generic; using UnityEngine; public static class FloatSmoother { public static List<float> GaussianSmooth(List<float> floats, int width, float sigma = -1f) { List<float> results = new List<float>(); // 确保核宽度为奇数 if (width % 2 == 0) width -= 1; int halfWidth = width / 2; // 预计算高斯核权重 float[] kernel = new float[width]; float totalWeight = 0f; // 默认sigma:核宽度/6,覆盖±3σ范围 if (sigma < 0) sigma = width / 6f; float twoSigmaSquared = 2 * sigma * sigma; for (int j = 0; j < width; j++) { // 计算当前位置到核中心的距离 int distance = j - halfWidth; // 高斯公式计算权重 kernel[j] = Mathf.Exp(-(distance * distance) / twoSigmaSquared); totalWeight += kernel[j]; } // 遍历每个点计算平滑值 for (int i = 0; i < floats.Count; i++) { float result = 0f; float currentTotalWeight = 0f; // 处理边界截断时的实际权重和 for (int j = 0; j < width; j++) { int index = i - halfWidth + j; // 边界截断处理(和原逻辑一致) index = Mathf.Clamp(index, 0, floats.Count - 1); // 加权累加 result += floats[index] * kernel[j]; currentTotalWeight += kernel[j]; } // 用实际权重和归一化,避免边界偏差 result /= currentTotalWeight; results.Add(result); } return results; } }
关键细节说明
- σ的选择:如果需要更平滑的效果可以调大σ,更锐利则调小。默认值是根据核宽度自动计算的合理值,也可以手动传入自定义值。
- 边界处理:保留了你原有的
Clamp逻辑避免越界,同时在边界位置重新计算实际权重和,保证归一化的准确性。 - 性能优化:把核计算放在外层循环,避免重复计算,提升效率。
内容的提问来源于stack exchange,提问作者arcadeperfect
相关产品推荐
相关产品推荐

