如何在python中使用二维卷积生成二维高斯核?

问题描述

来自我的锻炼说明:

二维高斯可以通过一维高斯与其转置的卷积形成。

这是我的一维高斯函数

def gauss1d(sigma,filter_length=11):
    # INPUTS
    # @ sigma         : sigma of gaussian distribution
    # @ filter_length : integer denoting the filter length
    # OUTPUTS
    # @ gauss_filter  : 1D gaussian filter without normalization

    rng = range(-int(filter_length/2),int(filter_length/2)+1)
    gauss_filter = [np.exp((-x**2) / (2*sigma**2)) for x in rng]

    # The formula used above has been given in the instruction.
    return np.array(gauss_filter)

以及在图像和过滤器之间执行 2D 卷积的 2d 卷积函数,图像是 2D 图像。

def myconv2(image,filt):
    # INPUTS
    # @ image         : 2D image,as numpy array of size mxn
    # @ filt          : 1D or 2D filter of size kxl
    # OUTPUTS
    # img_filtered    : 2D filtered image,of size (m+k-1)x(n+l-1)

    m,n = image.shape
    k,l = filt.shape
    offsety = k // 2
    offsetx = l // 2
    img_filtered = np.zeros((m+k-1,n+l-1),"double")
    image = np.pad(image,((offsety,offsety),(offsetx,offsetx)),mode='constant')
    
    for i in range(offsety,m+offsety):
        for j in range(offsetx,n+offsetx):
            Box_vals = image[ i - offsety : i + offsety+1,j-offsetx: j+offsetx+1]
            new_val = np.sum( filt *  Box_vals)
            img_filtered[i][j] = np.sum(new_val)
    return img_filtered

函数如何适用于 5x5 输入图像和 3x3 滤波器内核的简单演示:

enter image description here

具有以下一维高斯及其转置,我调用 myconv2 函数

sigma = 3
filter_length = 5

gauss = gauss1d(sigma,filter_length).reshape(1,filter_length)
guass
array([[0.18073067,0.20897821,0.22058223,0.18073067]]) 

gauss_t = np.transpose(gauss)
gauss_t 
array([[0.18073067],[0.20897821],[0.22058223],[0.18073067]])

myconv2(gauss,guass_t)
array([[0.,0.,0.        ],[0.,[0.03986597,0.04609688,0.04865652,0.03986597],0.        ]])

正如你所看到的,它实际上不是一个二维高斯核,并且缺少一些值。 我不知道我缺少什么以及我应该在代码中考虑什么才能达到目标。 谢谢。

解决方法

你可以做一个矩阵乘法。卷积也应该有效,只是要注意填充。

gaus2d = gauss.T @ gauss

您的 conv2d 实现似乎不正确。我建议您实施“有效”卷积(或互相关):

simple_valid_cross_correlation(img,filt):
    ih,iw = img.shape
    fh,fw = filt.shape
    result = np.zeros((ih - fh + 1,iw - fw + 1))
    for i in range(result.shape[0]):
        for j in range(result.shape[1]):
            result[i,j] = np.sum(filt * img[i:i+fh,j:j+fw])
    return result

gauss_pad = np.pad(gauss.T,((0,0),(gauss.shape[1]-1,gauss.shape[1]-1)))
gauss2d = simple_valid_cross_correlation(gauss_pad,gauss)

如果您不想实现自己的转化,还有 scipy.signal.convolve2d。我觉得可能会更快

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...