python - 如何对 4D numpy 数组执行迭代 2D 操作

标签 python image-processing numpy multidimensional-array scipy

让我在这篇文章的开头声明我是 Python 和 NumPy 的新手,所以我确定我忽略了一些简单的事情。我想做的是使用掩码(掩码卷积操作)对 PGM(灰度)文件进行图像处理;但是,我不想使用可用的 SciPy 一体式成像处理库来完成此操作 — 我正在尝试自己实现 mask 和处理操作。我想要做的是:

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

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

所以,在上面的例子中,4 会回到它来自的 3x3 窗口的中心位置(在所有操作结束之后),所以它看起来像 [ [1, 1, 1], [0, 4, 1], [0, 0, 1]] 等获得的每个其他卷积特征。也可以对原件制作非引用副本,并将这个新值插入其中。

所以,这就是我到目前为止所做的:我有一个 256x256 二维 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/GameOfLifeStrides 等来源的研究, http://www.johnvinyard.com/blog/?p=268 , 和 http://chintaksheth.wordpress.com/2013/07/31/numpy-the-tricks-of-the-trade-part-ii/非常有帮助(以及 SO),但它们似乎并没有解决我正在尝试做的事情(除非我遗漏了一些明显的东西)。我可能会使用大量的 for 循环,但我更愿意学习如何使用我们拥有的这些很棒的 Python 库来完成它。我也意识到我将几个问题结合在一起,但这只是因为我暗暗怀疑这一切都可以非常简单地完成!在此先感谢您的帮助!

最佳答案

当您需要按元素乘法,然后通过加法减少时,请考虑 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)

关于python - 如何对 4D numpy 数组执行迭代 2D 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21743871/

相关文章:

python - 求凹曲线形状 Blob 的宽度和高度

c++ - OpenCV/C++ 程序比它的 numpy 对应程序慢,我该怎么办?

python - 使用python将图像转换为矩阵

python - 通过 2D 数组作为索引范围对 1D 数组进行 Numpy View

python - 迭代多个 numpy 数组并处理当前和先前元素的有效方法?

python - 打印格式化的值集列表

Python 使用 "~"符号从不同目录导入

python - 生成一维高斯核的最简单方法

python - Dask:无法从单独的 multiprocessing.Process 向全局客户端提交任务

python - 如何列出 celery 中的排队项目?