Saltar al contenido

¿Cómo calcular una matriz de kernel gaussiana de manera eficiente en numpy?

Si encuentras algún error con tu código o trabajo, recuerda probar siempre en un entorno de testing antes añadir el código al trabajo final.

Solución:

Yo mismo usé la respuesta aceptada para mi procesamiento de imágenes, pero la encuentro (y las otras respuestas) demasiado dependiente de otros módulos. Por lo tanto, aquí está mi solución compacta:

import numpy as np

def gkern(l=5, sig=1.):
    """
    creates gaussian kernel with side length l and a sigma of sig
    """

    ax = np.linspace(-(l - 1) / 2., (l - 1) / 2., l)
    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)

Editar: se cambió un rango a linspace para manejar incluso longitudes laterales

¿Desea utilizar el kernel gaussiano para, por ejemplo, suavizar imágenes? Si es así, hay una función. gaussian_filter() en scipy:

respuesta actualizada

Esto debería funcionar: aunque todavía no es 100% preciso, intenta dar cuenta de la masa de probabilidad dentro de cada celda de la cuadrícula. Creo que usar la densidad de probabilidad en el punto medio de cada celda es un poco menos preciso, especialmente para núcleos pequeños. Consulte https://homepages.inf.ed.ac.uk/rbf/HIPR2/gsmooth.htm para ver un ejemplo.

import numpy as np
import scipy.stats as st

def gkern(kernlen=21, nsig=3):
    """Returns a 2D Gaussian kernel."""

    x = np.linspace(-nsig, nsig, kernlen+1)
    kern1d = np.diff(st.norm.cdf(x))
    kern2d = np.outer(kern1d, kern1d)
    return kern2d/kern2d.sum()

Probándolo en el ejemplo de la Figura 3 desde el enlace:

gkern(5, 2.5)*273

da

array([[ 1.0278445 ,  4.10018648,  6.49510362,  4.10018648,  1.0278445 ],
       [ 4.10018648, 16.35610171, 25.90969361, 16.35610171,  4.10018648],
       [ 6.49510362, 25.90969361, 41.0435344 , 25.90969361,  6.49510362],
       [ 4.10018648, 16.35610171, 25.90969361, 16.35610171,  4.10018648],
       [ 1.0278445 ,  4.10018648,  6.49510362,  4.10018648,  1.0278445 ]])

La respuesta original (aceptada) a continuación aceptada es incorrecta
La raíz cuadrada es innecesaria y la definición del intervalo es incorrecta.

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

Estoy tratando de mejorar la respuesta de FuzzyDuck aquí. Creo que este enfoque es más corto y más fácil de entender. Aquí estoy usando signal.scipy.gaussian para obtener el núcleo gaussiano 2D.

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

Graficarlo usando matplotlib.pyplot:

import matplotlib.pyplot as plt
plt.imshow(gkern(21), interpolation='none')

Kernel gaussiano trazado usando matplotlib

Te invitamos a corroborar nuestra función escribiendo un comentario y valorándolo te estamos eternamente agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *