2014-02-13 69 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

謝謝,會檢查一下! –