def GaussianMatrix(X,sigma):
row,col=X.shape
GassMatrix=np.zeros(shape=(row,row))
X=np.asarray(X)
i=0
for v_i in X:
j=0
for v_j in X:
GassMatrix[i,j]=Gaussian(v_i.T,v_j.T,sigma)
j+=1
i+=1
return GassMatrix
def Gaussian(x,z,sigma):
return np.exp((-(np.linalg.norm(x-z)**2))/(2*sigma**2))
Dies ist mein aktueller Weg. Gibt es eine Möglichkeit, die Matrix-Operation dazu zu verwenden? X ist die Datenpunkte.
Möchten Sie den Gaußschen Kernel für z. Bildglättung? Wenn ja, gibt es eine Funktion gaussian_filter()
in scipy:
Alternativ sollte dies funktionieren:
import numpy as np
import scipy.stats as st
def gkern(kernlen=21, nsig=3):
"""Returns a 2D Gaussian kernel array."""
interval = (2*nsig+1.)/(kernlen)
x = np.linspace(-nsig-interval/2., nsig+interval/2., kernlen+1)
kern1d = np.diff(st.norm.cdf(x))
kernel_raw = np.sqrt(np.outer(kern1d, kern1d))
kernel = kernel_raw/kernel_raw.sum()
return kernel
Eingang:
import matplotlib.pyplot as plt
plt.imshow(gkern(21), interpolation='none')
Ausgabe:
Sie können einfach eine einfache 2D Dirac-Funktion gaussian-filter filtern - /, das Ergebnis ist dann die verwendete Filterfunktion:
import numpy as np
import scipy.ndimage.filters as fi
def gkern2(kernlen=21, nsig=3):
"""Returns a 2D Gaussian kernel array."""
# create nxn zeros
inp = np.zeros((kernlen, kernlen))
# set element at the middle to one, a dirac delta
inp[kernlen//2, kernlen//2] = 1
# gaussian-smooth the dirac, resulting in a gaussian filter mask
return fi.gaussian_filter(inp, nsig)
Ich selbst habe die akzeptierte Antwort für meine Bildverarbeitung verwendet, aber ich finde es (und die anderen Antworten) zu abhängig von anderen Modulen. Außerdem führt die akzeptierte Antwort manchmal zu Kerneln mit vielen Null-Einträgen am Ende.
Deshalb hier meine kompakte Lösung:
import numpy as np
def gkern(l=5, sig=1.):
"""
creates gaussian kernel with side length l and a sigma of sig
"""
ax = np.arange(-l // 2 + 1., l // 2 + 1.)
xx, yy = np.meshgrid(ax, ax)
kernel = np.exp(-0.5 * (np.square(xx) + np.square(yy)) / np.square(sig))
return kernel / np.sum(kernel)
Ich versuche die Antwort von FuzzyDuck hier zu verbessern. Ich denke, dieser Ansatz ist kürzer und verständlicher. Hier verwende ich signal.scipy.gaussian
, um den 2D-Gaußschen Kernel zu erhalten.
import numpy as np
from scipy import signal
def gkern(kernlen=21, std=3):
"""Returns a 2D Gaussian kernel array."""
gkern1d = signal.gaussian(kernlen, std=std).reshape(kernlen, 1)
gkern2d = np.outer(gkern1d, gkern1d)
return gkern2d
Plotten Sie es mit matplotlib.pyplot
:
import matplotlib.pyplot as plt
plt.imshow(gkern(21), interpolation='none')
Eine 2D-Gaußsche Kernel-Matrix kann mit Numpy-Broadcasting berechnet werden.
def gaussian_kernel(size=21, sigma=3):
"""Returns a 2D Gaussian kernel.
Parameters
----------
size : float, the kernel size (will be square)
sigma : float, the sigma Gaussian parameter
Returns
-------
out : array, shape = (size, size)
an array with the centered gaussian kernel
"""
x = np.linspace(- (size // 2), size // 2)
x /= np.sqrt(2)*sigma
x2 = x**2
kernel = np.exp(- x2[:, None] - x2[None, :])
return kernel / kernel.sum()
Für kleine Kerngrößen sollte dies ziemlich schnell sein.
Hinweis: Dies erleichtert das Ändern des Sigma-Parameters in Bezug auf die akzeptierte Antwort.
linalg.norm
nimmt einen axis
-Parameter an. Mit einem kleinen Experiment stellte ich fest, dass ich die Norm für alle Kombinationen von Reihen mit berechnen konnte
np.linalg.norm(x[None,:,:]-x[:,None,:],axis=2)
Es erweitert x
in ein 3D-Array aller Unterschiede und übernimmt die Norm für die letzte Dimension.
So kann ich dies auf Ihren Code anwenden, indem Sie den Parameter axis
zu Ihrer Gaussian
hinzufügen:
def Gaussian(x,z,sigma,axis=None):
return np.exp((-(np.linalg.norm(x-z, axis=axis)**2))/(2*sigma**2))
x=np.arange(12).reshape(3,4)
GaussianMatrix(x,1)
produziert
array([[ 1.00000000e+00, 1.26641655e-14, 2.57220937e-56],
[ 1.26641655e-14, 1.00000000e+00, 1.26641655e-14],
[ 2.57220937e-56, 1.26641655e-14, 1.00000000e+00]])
Passend dazu:
Gaussian(x[None,:,:],x[:,None,:],1,axis=2)
array([[ 1.00000000e+00, 1.26641655e-14, 2.57220937e-56],
[ 1.26641655e-14, 1.00000000e+00, 1.26641655e-14],
[ 2.57220937e-56, 1.26641655e-14, 1.00000000e+00]])
Aufbauend auf der Antwort von Teddy Hartanto. Sie können einfach Ihre eigenen eindimensionalen Gaußschen Funktionen berechnen und dann mit np.outer
die zweidimensionale berechnen. Sehr schneller und effizienter Weg.
Mit dem folgenden Code können Sie auch unterschiedliche Sigmas für jede Dimension verwenden
import numpy as np
def generate_gaussian_mask(shape, sigma, sigma_y=None):
if sigma_y==None:
sigma_y=sigma
rows, cols = shape
def get_gaussian_fct(size, sigma):
fct_gaus_x = np.linspace(0,size,size)
fct_gaus_x = fct_gaus_x-size/2
fct_gaus_x = fct_gaus_x**2
fct_gaus_x = fct_gaus_x/(2*sigma**2)
fct_gaus_x = np.exp(-fct_gaus_x)
return fct_gaus_x
mask = np.outer(get_gaussian_fct(rows,sigma), get_gaussian_fct(cols,sigma_y))
return mask
Ich habe nur mit Numpy versucht
def get_gauss_kernel(size=3,sigma=1):
center=(int)(size/2)
kernel=np.zeros((size,size))
for i in range(size):
for j in range(size):
diff=np.sqrt((i-center)**2+(j-center)**2)
kernel[i,j]=np.exp(-(diff**2)/2*sigma**2)
return kernel/np.sum(kernel)
und dann anrufen
plt.imshow(get_gauss_kernel(5,1))