我正在使用python创建一个大小为5x5的高斯滤波器。
我看到这篇文章here,他们在那里谈论类似的事情,但我没有找到获得matlab函数fspecial('gaussian', f_wid, sigma)
的等效python代码的确切方法
还有其他办法吗?
我尝试使用以下代码:
size = 2
sizey = None
size = int(size)
if not sizey:
sizey = size
else:
sizey = int(sizey)
x, y = scipy.mgrid[-size: size + 1, -sizey: sizey + 1]
g = scipy.exp(- (x ** 2/float(size) + y ** 2 / float(sizey)))
print g / np.sqrt(2 * np.pi)
获得的输出是
[[ 0.00730688 0.03274718 0.05399097 0.03274718 0.00730688]
[ 0.03274718 0.14676266 0.24197072 0.14676266 0.03274718]
[ 0.05399097 0.24197072 0.39894228 0.24197072 0.05399097]
[ 0.03274718 0.14676266 0.24197072 0.14676266 0.03274718]
[ 0.00730688 0.03274718 0.05399097 0.03274718 0.00730688]]
我想要的是这样的:
0.0029690 0.0133062 0.0219382 0.0133062 0.0029690
0.0133062 0.0596343 0.0983203 0.0596343 0.0133062
0.0219382 0.0983203 0.1621028 0.0983203 0.0219382
0.0133062 0.0596343 0.0983203 0.0596343 0.0133062
0.0029690 0.0133062 0.0219382 0.0133062 0.0029690
答案 0 :(得分:32)
一般而言,如果你真的关心得到与MATLAB完全相同的结果,最简单的方法就是直接查看MATLAB函数的来源。
在这种情况下,edit fspecial
:
...
case 'gaussian' % Gaussian filter
siz = (p2-1)/2;
std = p3;
[x,y] = meshgrid(-siz(2):siz(2),-siz(1):siz(1));
arg = -(x.*x + y.*y)/(2*std*std);
h = exp(arg);
h(h<eps*max(h(:))) = 0;
sumh = sum(h(:));
if sumh ~= 0,
h = h/sumh;
end;
...
很简单,嗯?将其移植到Python是<10分钟的工作:
import numpy as np
def matlab_style_gauss2D(shape=(3,3),sigma=0.5):
"""
2D gaussian mask - should give the same result as MATLAB's
fspecial('gaussian',[shape],[sigma])
"""
m,n = [(ss-1.)/2. for ss in shape]
y,x = np.ogrid[-m:m+1,-n:n+1]
h = np.exp( -(x*x + y*y) / (2.*sigma*sigma) )
h[ h < np.finfo(h.dtype).eps*h.max() ] = 0
sumh = h.sum()
if sumh != 0:
h /= sumh
return h
这给了我与舍入错误内的fspecial
相同的答案:
>> fspecial('gaussian',5,1)
0.002969 0.013306 0.021938 0.013306 0.002969
0.013306 0.059634 0.09832 0.059634 0.013306
0.021938 0.09832 0.1621 0.09832 0.021938
0.013306 0.059634 0.09832 0.059634 0.013306
0.002969 0.013306 0.021938 0.013306 0.002969
: matlab_style_gauss2D((5,5),1)
array([[ 0.002969, 0.013306, 0.021938, 0.013306, 0.002969],
[ 0.013306, 0.059634, 0.09832 , 0.059634, 0.013306],
[ 0.021938, 0.09832 , 0.162103, 0.09832 , 0.021938],
[ 0.013306, 0.059634, 0.09832 , 0.059634, 0.013306],
[ 0.002969, 0.013306, 0.021938, 0.013306, 0.002969]])
答案 1 :(得分:4)
你也可以尝试这个(作为2个独立的1D高斯随机变量的乘积)来获得2D高斯核:
from numpy import pi, exp, sqrt
s, k = 1, 2 # generate a (2k+1)x(2k+1) gaussian kernel with mean=0 and sigma = s
probs = [exp(-z*z/(2*s*s))/sqrt(2*pi*s*s) for z in range(-k,k+1)]
kernel = np.outer(probs, probs)
print kernel
#[[ 0.00291502 0.00792386 0.02153928 0.00792386 0.00291502]
#[ 0.00792386 0.02153928 0.05854983 0.02153928 0.00792386]
#[ 0.02153928 0.05854983 0.15915494 0.05854983 0.02153928]
#[ 0.00792386 0.02153928 0.05854983 0.02153928 0.00792386]
#[ 0.00291502 0.00792386 0.02153928 0.00792386 0.00291502]]
import matplotlib.pylab as plt
plt.imshow(kernel)
plt.colorbar()
plt.show()
答案 2 :(得分:3)
我找到了类似的解决方案:
def fspecial_gauss(size, sigma):
"""Function to mimic the 'fspecial' gaussian MATLAB function
"""
x, y = numpy.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]
g = numpy.exp(-((x**2 + y**2)/(2.0*sigma**2)))
return g/g.sum()
答案 3 :(得分:2)
此函数实现类似于matlab中的fspecial的功能
http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.get_window.html 来自scipy导入信号
>>>signal.get_window(('gaussian',2),3)
>>>array([ 0.8824969, 1. , 0.8824969])
此函数似乎只生成1D内核
我猜你可以实现代码来自己生成高斯模板,以及其他人已经指出过。
答案 4 :(得分:0)
嗨我认为问题在于对于高斯滤波器,归一化因子取决于您使用的维数。
所以过滤器看起来像这个
你错过的是归一化因子的平方!并且由于计算的准确性,需要对整个矩阵进行重整化!
代码附在此处:
def gaussian_filter(shape =(5,5), sigma=1):
x, y = [edge /2 for edge in shape]
grid = np.array([[((i**2+j**2)/(2.0*sigma**2)) for i in xrange(-x, x+1)] for j in xrange(-y, y+1)])
g_filter = np.exp(-grid)/(2*np.pi*sigma**2)
g_filter /= np.sum(g_filter)
return g_filter
print gaussian_filter()
未标准化为1:
之和的输出[[ 0.00291502 0.01306423 0.02153928 0.01306423 0.00291502]
[ 0.01306423 0.05854983 0.09653235 0.05854983 0.01306423]
[ 0.02153928 0.09653235 0.15915494 0.09653235 0.02153928]
[ 0.01306423 0.05854983 0.09653235 0.05854983 0.01306423]
[ 0.00291502 0.01306423 0.02153928 0.01306423 0.00291502]]
输出除以np.sum(g_filter):
[[ 0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]
[ 0.01330621 0.0596343 0.09832033 0.0596343 0.01330621]
[ 0.02193823 0.09832033 0.16210282 0.09832033 0.02193823]
[ 0.01330621 0.0596343 0.09832033 0.0596343 0.01330621]
[ 0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]]
答案 5 :(得分:0)
这里提供一个nd高斯窗口生成器:
def gen_gaussian_kernel(shape, mean, var):
coors = [range(shape[d]) for d in range(len(shape))]
k = np.zeros(shape=shape)
cartesian_product = [[]]
for coor in coors:
cartesian_product = [x + [y] for x in cartesian_product for y in coor]
for c in cartesian_product:
s = 0
for cc, m in zip(c,mean):
s += (cc - m)**2
k[tuple(c)] = exp(-s/(2*var))
return k
此函数将为您提供具有给定形状,中心和方差的非标准化高斯窗口。 例如: gen_gaussian_kernel(shape =(3,3,3),mean =(1,1,1),var = 1.0)output-&gt;
[[[ 0.22313016 0.36787944 0.22313016]
[ 0.36787944 0.60653066 0.36787944]
[ 0.22313016 0.36787944 0.22313016]]
[[ 0.36787944 0.60653066 0.36787944]
[ 0.60653066 1. 0.60653066]
[ 0.36787944 0.60653066 0.36787944]]
[[ 0.22313016 0.36787944 0.22313016]
[ 0.36787944 0.60653066 0.36787944]
[ 0.22313016 0.36787944 0.22313016]]]
答案 6 :(得分:0)
嘿,我认为这可能对您有帮助
import numpy as np
import cv2
def gaussian_kernel(dimension_x, dimension_y, sigma_x, sigma_y):
x = cv2.getGaussianKernel(dimension_x, sigma_x)
y = cv2.getGaussianKernel(dimension_y, sigma_y)
kernel = x.dot(y.T)
return kernel
g_kernel = gaussian_kernel(5, 5, 1, 1)
print(g_kernel)
[[0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]
[0.01330621 0.0596343 0.09832033 0.0596343 0.01330621]
[0.02193823 0.09832033 0.16210282 0.09832033 0.02193823]
[0.01330621 0.0596343 0.09832033 0.0596343 0.01330621]
[0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]]
答案 7 :(得分:0)
使用高斯PDF并假设空间不变模糊
def gaussian_kernel(sigma, size):
mu = np.floor([size / 2, size / 2])
size = int(size)
kernel = np.zeros((size, size))
for i in range(size):
for j in range(size):
kernel[i, j] = np.exp(-(0.5/(sigma*sigma)) * (np.square(i-mu[0]) +
np.square(j-mu[0]))) / np.sqrt(2*math.pi*sigma*sigma)```
kernel = kernel/np.sum(kernel)
return kernel