2014-02-13 40 views
4

让我先说这篇文章,说我对Python和NumPy很新,所以我确信我忽略了一些简单的东西。我想要做的是使用掩码(掩膜卷积操作)通过PGM(灰度)文件进行图像处理;但是,我不想使用SciPy一体化成像处理库来实现这一功能 - 我正试图自己实施掩蔽和处理操作。我想要做的是以下内容:如何在4D numpy阵列上执行迭代2D操作

  1. 迭代的3×3的滑动窗口上面的256×256阵列
  2. 在每次迭代中,我想执行一个3×3的图像掩模的操作(阵列包括分数值<的1)和从我的原始阵列
  3. 操作的3×3窗口的是,图像掩模得到由3×3窗口相乘,并且结果得到概括成一个数,它代表了原始的3×3区域的加权平均
  4. 这个总和应该被插回到3x3窗口的中心,原始的周围值原封不动
  5. 但是,其中一个操作的输出不应该是下一个操作的输入,因此应该创建一个新数组或者在原来的所有操作完成之前不应更新原始的256x256数组。

这个过程有点像这样,除了我需要把卷积功能的结果返回到窗口的它来自中心: http://ufldl.stanford.edu/wiki/images/6/6c/Convolution_schematic.gif

因此,在上述例子中, 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库。我也意识到我将几个问题结合在一起,但那只是因为我有一个偷偷摸摸的猜测,这可以做得很简单!预先感谢任何帮助!

+0

你没事用[convolve2d](http://docs.scipy.org/doc/sci PY /参考/生成/ scipy.signal.convolve2d.html)? – perimosocordiae

+0

您能否提供一个简单的使用案例,因为它可能与我的情况有关?我确实看过一些“convolve”函数,但它们似乎并没有完成我之前的工作。 –

回答

3

当你需要乘逐个元件,然后用另外减少,认为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) 
+0

这是完美的 - 非常感谢!你能解释一下'np.einsum'在这里做了什么,无论它是如何乘法和求和'arr_view'和'mask',以及如何构造'ijkl'参数?我之前曾经查过一些例子,但是并没有真正弄清楚如何针对我所要做的事情进行调整。我明白'arr'指数会出现什么情况,尽管来自'c'语言系列有点疯狂,可以用数组索引来做到这一点! –

1

基于示例说明:

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]]) 
+0

谢谢,会检查一下! –