如何在 python 中使用二维卷积生成二维高斯核?
How to generate 2d gaussian kernel using 2d convolution in python?
来自我的锻炼指导:
A 2D Gaussian can be formed by convolution of a 1D Gaussian with its transpose.
这是我的一维高斯函数:
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)
和二维卷积函数,它在图像和滤波器之间执行二维卷积,图像是二维图像。
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 滤波器内核:
有了以下 1d 高斯及其转置,我调用 myconv2
函数:
sigma = 3
filter_length = 5
gauss = gauss1d(sigma, filter_length).reshape(1,filter_length)
guass
array([[0.18073067, 0.20897821, 0.22058223, 0.20897821, 0.18073067]])
gauss_t = np.transpose(gauss)
gauss_t
array([[0.18073067],
[0.20897821],
[0.22058223],
[0.20897821],
[0.18073067]])
myconv2(gauss, guass_t)
array([[0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0. , 0. ],
[0.03986597, 0.04609688, 0.04865652, 0.04609688, 0.03986597],
[0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0. , 0. ]])
如您所见,它实际上不是二维高斯核,并且缺少一些值。 我不知道我缺少什么以及我的代码应该考虑什么才能达到目标。 谢谢。
你可以做一个矩阵乘法。卷积也应该有效,只是要注意填充。
gaus2d = gauss.T @ gauss
您的 conv2d 实现似乎不正确。我建议你实现一个 'valid' 卷积(或互相关):
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
。我认为它可能会更快