31

我正在使用 python 创建一个大小为 5x5 的高斯滤波器。我在这里看到了这篇文章,他们谈论了类似的事情,但我没有找到将等效的 python 代码获取到 matlab 函数的确切方法fspecial('gaussian', f_wid, sigma) 有没有其他方法可以做到这一点?我尝试使用以下代码:

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
4

8 回答 8

45

一般来说,如果您真的关心获得与 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]])
于 2013-06-19T21:27:45.863 回答
11

我为这个问题找到了类似的解决方案:

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()
于 2015-01-13T17:58:49.623 回答
9

您也可以尝试这个(作为 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()

在此处输入图像描述

于 2017-08-18T20:35:19.733 回答
3

这个函数实现的功能类似于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])

这个函数似乎只生成一维内核

我想你可以自己实现代码来生成一个高斯掩码,就像其他人指出的那样。

于 2013-12-11T06:34:38.490 回答
1

嘿,我想这可能对你有帮助

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]]
于 2019-10-23T14:46:57.607 回答
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
于 2020-10-13T06:01:00.290 回答
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]]
于 2016-03-06T20:47:22.737 回答
0

这里是提供一个nd-gaussian窗口生成器:

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)] = np.exp(-s/(2*var))
    return k

此函数将为您提供具有给定形状、中心和方差的非归一化高斯窗口。例如:gen_gaussian_kernel(shape=(3,3,3),mean=(1,1,1),var=1.0) output->

[[[ 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]]]
于 2017-02-22T04:32:06.727 回答