生成一维高斯核的最简单方法

10 投票
2 回答
19954 浏览
提问于 2025-04-17 16:07

我在想,生成一个一维高斯核的最简单方法是什么,给定滤波器的长度。在我看来,应该是对向量[-滤波器长度,...,滤波器长度]的正态分布进行计算,这样理解对吗?

到目前为止,我做了这个,但我不知道为什么不对:

result = np.zeros( filter_length )

mid = filter_length/2
result=[(1/(sigma*np.sqrt(2*np.pi)))*(1/(numpy.exp((i**2)/(2*sigma**2)))) for i in range(-mid,mid+1)]  

return result

这里的sigma是标准差,是一个参数。filter-length也是一个参数。

之所以不对,是因为比如说当长度=3,sigma=math.sqrt(1.0/2/math.log(2))时,我得到的结果是:

[0.23485931967491286, 0.46971863934982572, 0.23485931967491286]

但应该是:

[0.25, 0.5, 0.25]

所以,是不是有四舍五入的问题?我不知道发生了什么……

编辑 我觉得我应该以某种方式进行截断。

问题解决 问题在于我没有进行归一化。我需要把向量的每个元素都除以它们的总和。

2 个回答

0

对于喜欢有完整可复制粘贴代码示例的人:

import numpy as np

filter_length = 3
sigma=math.sqrt(1.0/2/math.log(2))
result = np.zeros( filter_length )

mid = int(filter_length/2)
result=[(1/(sigma*np.sqrt(2*np.pi)))*(1/(np.exp((i**2)/(2*sigma**2)))) for i in range(-mid,mid+1)]  
sumresult = np.sum(result)
print(result/sumresult)

[0.25 0.5 0.25]

5

我对numpy的语法不是很熟悉,但如果你把一个卷积核和一个狄拉克脉冲(Dirac impulse)进行卷积,你会得到和这个卷积核一样的输出。

所以你可以直接使用内置的 scipy.ndimage.filters.gaussian_filter1d 函数,把这个数组作为输入:[ 0, 0, 0, ... 0, 1, 0, ...0, 0, 0]

输出应该是一个高斯核,最高点的值为1。(如果你想要不同的最大值,可以把1替换成你想要的值)

总的来说,你会得到gaussian_filter1d函数内部使用的高斯核作为输出。这应该是生成高斯核最简单、出错可能性最小的方法,你也可以用同样的方法生成一个二维的核,只需使用相应的scipy二维函数。当然,如果你的目标是从头开始做,那么这个方法只是作为参考比较好。

关于你的公式:
要想用你的公式得到[..., 0.5, ...]这样的输出,你需要解这个方程:
(1/(sigma*np.sqrt(2*np.pi)) = 0.5
所以正确的sigma应该是:
sigma = math.sqrt(2*1/np.pi)

撰写回答