How to perform an iterative 2D operation in a 4D numpy array

Let me preface this post by saying that I'm pretty new to Python and NumPy, so I'm sure I'm missing something simple. What I'm trying to do is image processing through a PGM (grayscale) file using a mask (mask convolution operation); however, I do not want to do this using the available SciPy all-in-one image processing libraries, which I am trying to implement myself. I want to do the following:

  • Iterate a 3x3 sliding window over a 256x256 array.
  • At each iteration, I want to perform an operation with a 3x3 image mask (an array consisting of fractional values ​​<1) and a 3x3 window from my original array
  • The operation is that the image mask is multiplied by a 3x3 window and the results are reduced to one number, which is the weighted average of the original 3x3 region.
  • This amount should be inserted back into the center of the 3x3 window, while the original surrounding values ​​remain intact.
  • However, the output of one of these operations should not be the input of the next operation, so a new array must be created or the original 256x256 array should not be updated until all operations are completed.

The process is similar to this, except that I need to return the result of the minimized function back to the center of the window from which it came: 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,, 4D numpy 33 . , , , , . , npsum, , . 256x256 , , , 3x3 . ndenumerate (v, x, 1, 1) 4D- , , 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 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), , , , m ( - ). , for, Python, . , , , , ! !

+4
2

, , np.dot np.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)
+3

:

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

Source: https://habr.com/ru/post/1526658/


All Articles