【问题标题】:How to perform iterative 2D operation on 4D numpy array如何对 4D numpy 数组执行迭代 2D 操作
【发布时间】:2014-03-11 17:15:50
【问题描述】:

让我先说我对 Python 和 NumPy 还很陌生,所以我确定我忽略了一些简单的东西。我要做的是使用掩码(掩码卷积操作)对 PGM(灰度)文件进行图像处理;但是,我不想使用可用的 SciPy 一体式成像处理库来执行此操作——我正在尝试自己实现遮罩和处理操作。我想做的是:

  1. 在 256x256 数组上迭代 3x3 滑动窗口
  2. 在每次迭代中,我想使用 3x3 图像掩码(由小数值
  3. 操作是图像掩码乘以 3x3 窗口,结果相加为一个数字,表示原始 3x3 区域的加权平均值
  4. 这个总和应该被插回到 3x3 窗口的中心,而原始周围的值保持不变
  5. 但是,其中一个操作的输出不应成为下一个操作的输入,因此应创建一个新数组或在所有操作完成之前更新原始 256x256 数组。

这个过程有点像这样,除了我需要将卷积特征的结果放回它来自的窗口的中心:
(来源:stanford.edu

因此,在上面的示例中,4 将回到它来自的 3x3 窗口的中心位置(在所有操作结束之后),所以它看起来像 [[1, 1, 1], [0, 4, 1], [0, 0, 1]],以此类推得到的卷积特征。也可以对原始副本进行非参考副本,并将此新值插入其中。

所以,这就是我到目前为止所做的:我有一个 256x256 2D numpy 数组,这是我的源图像。使用as_strided,,我将其转换为 3x3 切片的 4D numpy 数组。我面临的主要问题是我想在每个切片上执行我指定的操作。我可以在一个切片上执行它,但是在我尝试过的npsum 操作中,它将所有切片的结果加起来为一个值。在此之后,我要么想以我所描述的方式创建一个带有结果的新 256x256 数组,要么迭代原始数组,酌情替换每个 3x3 窗口的中间值。我尝试使用ndenumerate 每次更改我的 4D 数组的相同值 (v, x, 1, 1),但由于从我的 4D 数组返回的索引的形式为 (v, x, y, z), 我似乎无法弄清楚如何仅遍历 (v, x) 并将最后两部分保留为根本不应该更改的常量。

到目前为止,这是我的代码:

import numpy as np
from numpy.lib import stride_tricks

# create 256x256 NumPy 2D array from image data and image size so we can manipulate the image data, then create a 4D array of strided windows
# currently, it's only creating taking 10 slices to test with
imageDataArray = np.array(parsedPGMFile.imageData, dtype=int).reshape(parsedPGMFile.numRows, parsedPGMFile.numColumns)
xx = stride_tricks.as_strided(imageDataArray, shape=(1, 10, 3, 3), strides=imageDataArray.strides + imageDataArray.strides)

# create the image mask to be used
mask = [1,2,1,2,4,2,1,2,1]
mask = np.array(mask, dtype=float).reshape(3, 3)/16

# this will execute the operation on just the first 3x3 element of xx, but need to figure out how to iterate through all elements and perform this operation individually on each element
result = np.sum(mask * xx[0,0])

来自 http://wiki.scipy.org/Cookbook/GameOfLifeStrideshttp://www.johnvinyard.com/blog/?p=268http://chintaksheth.wordpress.com/2013/07/31/numpy-the-tricks-of-the-trade-part-ii/ 等来源的研究非常有帮助(以及 SO),但它们似乎并没有解决我正在尝试做的事情(除非我遗漏了一些明显的东西)。我可能会使用大量的 for 循环,但我宁愿学习如何使用我们拥有的这些很棒的 Python 库来做到这一点。我也意识到我将几个问题组合在一起,但这只是因为我有一种偷偷摸摸的怀疑,这一切都可以非常简单地完成!提前感谢您的帮助!

【问题讨论】:

  • 你可以使用convolve2d吗?
  • 您能否提供一个简单的用例,因为它可能与我的情况有关?我确实查看了一些 convolve 函数,但它们似乎并没有达到我想要的效果。

标签: python image-processing numpy multidimensional-array scipy


【解决方案1】:

当您需要逐元素相乘,然后通过加法减少时,请考虑np.dotnp.einsum

from numpy.lib.stride_tricks import as_strided
arr = np.random.rand(256, 256)
mask = np.random.rand(3, 3)
arr_view = as_strided(arr, shape=(254, 254, 3, 3), strides=arr.strides*2)

arr[1:-1, 1:-1] = np.einsum('ijkl,kl->ij', arr_view, mask)

【讨论】:

  • 这太完美了——非常感谢!您能否解释一下np.einsum 在这里做了什么,包括它如何将arr_viewmask 相乘和求和,以及如何构造ijkl 参数?我之前曾用它查找过一些示例,但无法真正弄清楚如何根据我想要做的事情来调整它。我了解arr 索引的情况,尽管来自c 系列语言,但使用数组索引可以做到这一点有点疯狂!
【解决方案2】:

根据示例说明:

In [1]: import numpy as np

In [2]: from scipy.signal import convolve2d

In [3]: image = np.array([[1,1,1,0,0],[0,1,1,1,0],[0,0,1,1,1],[0,0,1,1,0],[0,1,1,0,0]])

In [4]: m = np.array([[1,0,1],[0,1,0],[1,0,1]])

In [5]: convolve2d(image, m, mode='valid')
Out[5]:
array([[4, 3, 4],
       [2, 4, 3],
       [2, 3, 4]])

然后把它放回原来的地方:

In [6]: image[1:-1,1:-1] = convolve2d(image, m, mode='valid')

In [7]: image
Out[7]:
array([[1, 1, 1, 0, 0],
       [0, 4, 3, 4, 0],
       [0, 2, 4, 3, 1],
       [0, 2, 3, 4, 0],
       [0, 1, 1, 0, 0]])

【讨论】:

  • 谢谢,过会检查一下!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 2020-08-22
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 2019-03-02
相关资源
最近更新 更多