首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高斯卷积vs高斯滤波器

高斯卷积vs高斯滤波器
EN

Stack Overflow用户
提问于 2018-04-23 19:42:49
回答 2查看 2.4K关注 0票数 1

简单的任务..我想用高斯来平滑一些向量..这只是一个测试用例,稍后我想将其应用于图像。

代码语言:javascript
复制
import numpy as np
import scipy.stats
import scipy.ndimage

m = 7  # size of the 'signal'
n = 7  # size of the filter
sgm = 2  # dev for standard distr
weight_conv = np.zeros(2*m*n).reshape(2*n, m)  # Weights for the convolution

input_signal = np.array(range(m))  # input signal..
x1 = np.linspace(-4*sgm, 4*sgm, n)  # x-values for the normal-dstr
input_filter = scipy.stats.norm.pdf(x1, loc=0, scale=sgm)

# create my own weight matrix
for i in range(weight_conv.shape[1]):
    weight_conv[i:(len(input_filter)+i), i] = input_filter

# My own way of calculating the convolution
np.sum(weight_conv * input_signal, axis=1)
# Convolution provided by numpy
np.convolve(input_signal, input_filter)
# Apply the scipy gaussian filter...
scipy.ndimage.filters.gaussian_filter(input_signal, sigma=sgm)
scipy.ndimage.filters.gaussian_filter1d(input_signal, sigma=sgm)

现在我的想法是,所有这些都应该是相似的。我的方法是产生与numpy卷积类似的输出,但scipy方法不同…

代码语言:javascript
复制
scipy.ndimage.filters.gaussian_filter(input_signal, sigma=sgm)
array([1, 1, 2, 3, 3, 4, 4])

现在的情况肯定是scipy在做一些不同的事情。但是什么呢?我不知道。我已经检查了源代码,在那里他们似乎只是使用高斯内核的卷积(这也是我正在做的)。但是答案并不合理。

有谁有不同的想法吗?

EN

回答 2

Stack Overflow用户

发布于 2018-04-23 23:02:17

在@filippo和这个SO-question的帮助下,我能够重新构建scipy实现。该方法将信息传播到两端的方式至关重要。

下面是一个代码片段,展示了它们是如何相等的

代码语言:javascript
复制
import numpy as np
import scipy.stats
import scipy.ndimage
import matplotlib.pyplot as plt
np.set_printoptions(linewidth=160)


m_init = 7
# Create any signal here...
input_signal_init = []  
input_signal_init = np.arange(m_init)
input_signal_init = np.random.choice(range(m_init),m_init)
# Convert to float for better results in scipy.
input_signal_init = np.array(input_signal_init).astype(float)

# Simulating method='reflect'
input_signal = np.array([*input_signal_init[::-1], *input_signal_init, *input_signal_init[::-1]])

# Define new length of input signal
m = len(input_signal)  
# Properties of the Gaussian
sgm = 2  # dev for standard distr
radius = 4 * sgm
x = numpy.arange(-radius, radius+1)
n = len(x)
weight_conv = np.zeros(m*(n+m)).reshape(n+m, m)  

# Calculate the gaussian
p = np.polynomial.Polynomial([0, 0, -0.5 / (sgm * sgm)])
input_filter = numpy.exp(p(x), dtype=numpy.double)
input_filter /= input_filter.sum()

# Calculate the filter weights
for i in range(weight_conv.shape[1]):
    weight_conv[i:(len(input_filter)+i), i] = input_filter

# My own way of calculating the convolution
self_conv = np.sum(weight_conv * input_signal, axis=1)[(2*m_init+1):(3*m_init+1)]
# Convolution provided by numpy
numpy_conv = np.convolve(input_signal, input_filter)[(2*m_init+1):(3*m_init+1)]
# Convolution by scipy with method='reflect'
# !! Here we use t[![enter image description here][2]][2]he original 'input_signal_init'
scipy_conv = scipy.ndimage.filters.gaussian_filter(input_signal_init, sigma=sgm)

绘制结果总是让人相信你做得很好……所以

代码语言:javascript
复制
plt.plot(scipy_conv, 'r-')
plt.plot(self_conv, 'bo')
plt.plot(numpy_conv, 'k.-')
plt.show()

给出了以下image

还可以验证,将scipy滤波器的mode设置为'constant'也将创建相同的卷积。

票数 2
EN

Stack Overflow用户

发布于 2018-04-23 20:32:22

Scipy多维高斯滤波器使用更大的核。默认情况下,内核半径被截断为4 sigma,在您的情况下,这应该有点类似于17x17滤波器。

有关具体实现,请参阅_gaussian_kernel1d。它还使用了几个一维可分离的相关性,但这应该没有太大区别。

另一个关键区别是输出向量的大小和精度。来自ndimage文档:

中间数组以与输出相同的数据类型存储。因此,对于精度较低的输出类型,结果可能不精确,因为中间结果的存储精度可能不够高。这可以通过指定更精确的输出类型来防止。

因此,在您的情况下,输出精度受input_signal.dtype的限制。尝试对输出使用浮点输入数组或不同的数组。

输出大小和边缘处理有点棘手,不确定是否有方法可以从np.convolvescipy.ndimage.gaussian_filter获得相同的行为

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49980292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档