【问题标题】:Vectorizing 2D Convolutions in NumPy在 NumPy 中向量化 2D 卷积
【发布时间】:2020-06-18 04:20:36
【问题描述】:

我知道有各种优化的现成函数可用于执行 2D 卷积,但为了便于理解,我正在尝试实现我自己的 2D 卷积函数。

以下是我目前所做的:

    convoluted = []
    # TODO: Vectorize
    for i in range(0, M - m + 1):
        for j in range(0, N - n + 1):
            submatrix = x[i:i+m, j:j+n]
            convoluted.append(np.sum([submatrix*kernel]))
    convoluted = np.array(convoluted).reshape(M - m + 1, N - n + 1)

注意x是输入图像数组,(M, N)是输入图像的形状,(m, n)是使用的内核形状。

2 个显式的 for 循环相当很慢。
有什么办法可以矢量化吗?任何帮助表示赞赏
(我知道可以使用 python 列表推导,至少对于内部循环,但我正在寻找一种更快的方法,如果有的话)

【问题讨论】:

  • 向量化总是意味着 Numpy。这就是你所说的现成的函数。
  • google.com/search?q=python+convolution+numpy 其他人尝试了你在做什么,你应该可以找到一些源代码。
  • 附加到列表似乎效率低下。为什么不直接写入 NumPy 数组?
  • @CrisLuengo 你认为这会更快吗?因为我已经阅读了解释 np.append 比 list.append 慢得多的帖子。或者你的意思是拿一个 numpy 数组 a 并写 a[i, j] = ... ?
  • 是的,你知道输出的大小,你可以创建一个预期大小的数组并用你的计算结果填充它。

标签: python numpy computer-vision vectorization convolution


【解决方案1】:

我想你正在寻找这个:

from skimage.util.shape import view_as_windows
sub_matrices = view_as_windows(x, (m,n), 1)
convoluted = np.einsum('ij,klij->kl',kernel,sub_matrices)

第一行从您的原始数组创建内核大小的窗口。第二行是简单的乘法和加法(类似于 for 循环中的行,为它删除循环更优雅)。这个和你的代码的输出应该是一样的。如果您设置为不使用其中任何一个,请告诉我们您在编辑帖子时的限制。

另一种不使用 skimage 包的类似方法(仅使用 numpy 但稍长的代码)是here

【讨论】:

    猜你喜欢
    • 2018-01-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多