it-swarm.com.de

So erhalten Sie einen Gaußschen Filter in Python

Ich verwende Python, um einen Gaußschen Filter der Größe 5x5 zu erstellen. Ich habe diesen Beitrag hier gesehen - wo er über eine ähnliche Sache spricht, aber ich habe nicht den richtigen Weg gefunden, um gleichwertigen Python-Code für Matlab zu erhalten function fspecial('gaussian', f_wid, sigma) Gibt es eine andere Möglichkeit, dies zu tun? Ich habe versucht, folgenden Code zu verwenden:

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)

Die erhaltene Ausgabe ist 

[[ 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]]

Was ich will ist so etwas:

   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
16
Khushboo

Wenn Sie wirklich genau das gleiche Ergebnis wie MATLAB erhalten möchten, können Sie dies am einfachsten erreichen, indem Sie direkt auf die Quelle der MATLAB-Funktion schauen.

In diesem Fall 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;
...

Ganz einfach, wie? Es ist <10 Minuten Arbeit, dies nach Python zu portieren:

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

Dies gibt mir die gleiche Antwort wie fspecial innerhalb eines Rundungsfehlers:

 >> 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]])
27
ali_m

Sie könnten dies auch versuchen (als Produkt von 2 unabhängigen 1D-Gaußschen Zufallsvariablen), um einen 2D-Gaußschen Kern zu erhalten:

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()

 enter image description here

3
Sandipan Dey

Ich habe eine ähnliche Lösung für dieses Problem gefunden:

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
sparklearner

Diese Funktion implementiert ähnliche Funktionen wie fspecial in matlab 

http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.get_window.html aus dem scipy-Importsignal

>>>signal.get_window(('gaussian',2),3)
>>>array([ 0.8824969,  1.       ,  0.8824969])

Diese Funktion scheint nur 1D-Kernel zu generieren 

Ich vermute, Sie könnten Code implementieren, um eine Gaußsche Maske zu generieren, wie auch andere darauf hingewiesen haben.

2
SentinalBais

Hallo, ich denke, das Problem ist, dass der Normalisierungsfaktor für einen Gaußschen Filter von der Anzahl der verwendeten Dimensionen abhängt. Der Filter sieht also so ausformula
Was Sie vermissen, ist das Quadrat des Normalisierungsfaktors! Und wegen der Rechengenauigkeit müssen Sie die gesamte Matrix umnormieren! Der Code ist hier beigefügt:

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()

Die Ausgabe ohne normalisierte Summe von 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]]

Die Ausgabe geteilt durch 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]]
0
Gordon Tseng

hier ist ein nd-gaußscher Fenstergenerator bereitzustellen:

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

mit dieser Funktion erhalten Sie ein nicht normalisiertes Gauß-Fenster mit gegebener Form, Mittelpunkt und Varianz. zum Beispiel: gen_gaussian_kernel (Form = (3,3,3), Mittelwert = (1,1,1), var = 1,0) Ausgabe->

[[[ 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]]]
0
weiyixie