仅使用Numpy即可卷积2d [英] Convolve2d just by using Numpy
问题描述
我正在研究使用Numpy进行的图像处理,并且面临卷积滤波的问题.
I am studying image-processing using Numpy and facing a problem with filtering with convolution.
我想对灰度图像进行卷积. (将2d数组与较小的2d数组进行卷积)
有人有优化我的方法的想法吗?
Does anyone have an idea to refine my method ?
我知道 scipy 支持convolve2d但是我只想通过使用Numpy来进行卷积.
I know that scipy supports convolve2d but I want to make a convolve2d only by using Numpy.
首先,我将2d数组作为子矩阵.
First, I made a 2d array the submatrices.
a = np.arange(25).reshape(5,5) # original matrix
submatrices = np.array([
[a[:-2,:-2], a[:-2,1:-1], a[:-2,2:]],
[a[1:-1,:-2], a[1:-1,1:-1], a[1:-1,2:]],
[a[2:,:-2], a[2:,1:-1], a[2:,2:]]])
子矩阵看起来很复杂,但是下图显示了我正在做的事情.
the submatrices seems complicated but what I am doing is shown in the following drawing.
接下来,我将每个子矩阵乘以一个过滤器.
Next, I multiplied each submatrices with a filter.
conv_filter = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]])
multiplied_subs = np.einsum('ij,ijkl->ijkl',conv_filter,submatrices)
并对它们求和.
np.sum(np.sum(multiplied_subs, axis = -3), axis = -3)
#array([[ 6, 7, 8],
# [11, 12, 13],
# [16, 17, 18]])
因此该过程可以称为我的convolve2d.
Thus this procudure can be called my convolve2d.
def my_convolve2d(a, conv_filter):
submatrices = np.array([
[a[:-2,:-2], a[:-2,1:-1], a[:-2,2:]],
[a[1:-1,:-2], a[1:-1,1:-1], a[1:-1,2:]],
[a[2:,:-2], a[2:,1:-1], a[2:,2:]]])
multiplied_subs = np.einsum('ij,ijkl->ijkl',conv_filter,submatrices)
return np.sum(np.sum(multiplied_subs, axis = -3), axis = -3)
但是,我发现这个my_convolve2d麻烦的原因有3个.
However, I find this my_convolve2d troublesome for 3 reasons.
- 子矩阵的生成太笨拙,难以读取,只能在过滤器为3 * 3的情况下使用
- 可变子矩阵的大小似乎太大,因为它比原始矩阵大约9倍.
- 求和似乎有点不直观.简单地说,很丑.
感谢您阅读本文.
种类的更新.我为自己写了一个conv3d.我将其保留为公共领域.
Kind of update. I wrote a conv3d for myself. I will leave this as a public domain.
def convolve3d(img, kernel):
# calc the size of the array of submatracies
sub_shape = tuple(np.subtract(img.shape, kernel.shape) + 1)
# alias for the function
strd = np.lib.stride_tricks.as_strided
# make an array of submatracies
submatrices = strd(img,kernel.shape + sub_shape,img.strides * 2)
# sum the submatraces and kernel
convolved_matrix = np.einsum('hij,hijklm->klm', kernel, submatrices)
return convolved_matrix
推荐答案
您可以使用as_strided
要摆脱第二个丑陋"的总和,请更改您的einsum
,以便输出数组仅包含j
和k
.这意味着您需要进行第二次求和.
To get rid of your second "ugly" sum, alter your einsum
so that the output array only has j
and k
. This implies your second summation.
conv_filter = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]])
m = np.einsum('ij,ijkl->kl',conv_filter,sub_matrices)
# [[ 6 7 8]
# [11 12 13]
# [16 17 18]]
这篇关于仅使用Numpy即可卷积2d的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!