可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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))
This is my current way. Is there any way I can use matrix operation to do this? X is the data points.
回答1:
Do you want to use the Gaussian kernel for e.g. image smoothing? If so, there's a function gaussian_filter()
in scipy:
Alternatively, this should work:
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
Input:
import matplotlib.pyplot as plt plt.imshow(gkern(21), interpolation='none')
Output:
回答2:
You may simply gaussian-filter a simple 2D dirac function, the result is then the filter function that was being used:
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)
回答3:
I myself used the accepted answer for my image processing, but I find it (and the other answers) too dependent on other modules. Furthermore, the accepted answer sometimes produces kernels with a lot of zero entries in the end.
Therefore, here is my compact solution:
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(-(xx**2 + yy**2) / (2. * sig**2)) return kernel / np.sum(kernel)
回答4:
linalg.norm
takes an axis
parameter. With a little experimentation I found I could calculate the norm for all combinations of rows with
np.linalg.norm(x[None,:,:]-x[:,None,:],axis=2)
It expands x
into a 3d array of all differences, and takes the norm on the last dimension.
So I can apply this to your code by adding the axis
parameter to your Gaussian
:
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)
produces
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]])
Matching:
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]])
回答5:
I'm trying to improve on FuzzyDuck's answer here. I think this approach is shorter and easier to understand. Here I'm using signal.scipy.gaussian
to get the 2D gaussian kernel.
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
Plotting it using matplotlib.pyplot
:
import matplotlib.pyplot as plt plt.imshow(gkern(21), interpolation='none')

回答6:
Building up on Teddy Hartanto's answer. You can just calculate your own one dimensional Gaussian functions and then use np.outer
to calculate the two dimensional one. Very fast and efficient way.
With the code below you can also use different Sigmas for every dimension
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
回答7:
A 2D gaussian kernel matrix can be computed with numpy broadcasting,
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()
For small kernel sizes this should be reasonably fast.
Note: this makes changing the sigma parameter easier with respect to the accepted answer.