如何在4D numpy数组上执行迭代2D操作 [英] How to perform iterative 2D operation on 4D numpy array

查看:151
本文介绍了如何在4D numpy数组上执行迭代2D操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我在这篇文章前言说我对Python和NumPy很新,所以我确信我忽略了一些简单的事情。我要做的是使用掩码(掩模卷积操作)在PGM(灰度)文件上进行图像处理;但是,我不想使用可用的SciPy一体化成像处理库 - 我试图自己实现屏蔽和处理操作。我想做的是以下内容:


  1. 在256x256阵列上迭代3x3滑动窗口

  2. 在每次迭代中,我想使用3x3图像蒙版(由小数值<1组成的数组)和原始数组中的3x3窗口执行操作

  3. 操作是图像蒙版乘以3x3窗口,结果总计为一个数字,表示原始3x3区域的加权平均值

  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,我将它转换为4x numpy 3x3切片数组。我面临的主要问题是我想执行我在每个切片上指定的操作。我能够在一个切片上执行它,但是在我尝试过的 npsum 操作中,它将所有切片的结果加到一个值中。在此之后,我要么想要以我所描述的方式创建一个新的256x256数组,或者迭代原始数据,在适当时替换每个3x3窗口的中间值。我尝试使用 ndenumerate 更改我的4D的相同值(v,x,1,1)每次都有数组,但是因为从我的4D数组返回的索引的形式是(v,x,y,z),我似乎无法弄清楚如何只迭代(v,x)并将最后两部分作为常量保留,不应该改变。



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

 从numpy.lib导入numpy为np 
import stride_tricks

#从图像数据和图像大小创建256x256 NumPy 2D数组,这样我们就可以操作图像数据,然后创建一个四维数组的跨步窗口
#当前,它只创建需要10个切片来测试
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)

#创建图像要使用的掩码
mask = [1,2,1,2,4,2,1,2,1]
mask = np.array(mask,dtype = float).reshape(3 ,3)/ 16

#这将仅对xx的第一个3x3元素执行操作,但需要弄清楚如何遍历所有元素并在每个元素上单独执行此操作
result = np.sum(mask * xx [0,0])

来自<来源的研究a href =http://wiki.scipy.org/Cookbook/GameOfLifeStrides =nofollow noreferrer> http://wiki.scipy.org/Cookbook/GameOfLifeStrides , http://www.johnvinyard.com/blog/?p=268 ,以及 http://chintaksheth.wordpress.com/2013 / 07/31 / numpy-the-trade-of-trade-part-ii / 非常有帮助(以及SO),但它们似乎没有解决我正在尝试做的事情确切地说(除非我错过了一些很明显)。我可能会使用大量的用于循环,但我宁愿学习如何使用我们拥有的这些非常棒的Python库。我也意识到我正在将几个问题结合在一起,但这只是因为我怀疑这一切都可以非常简单地完成!在此先感谢您的帮助!

解决方案

当您需要按元素乘法,然后通过添加减少时,请认为 np.dot np.einsum

 来自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)


Let me preface this post by saying that I'm pretty new to Python and NumPy, so I'm sure I'm overlooking something simple. What I'm trying to do is image processing over a PGM (grayscale) file using a mask (a mask convolution operation); however, I don't want to do it using the SciPy all-in-one imaging processing libraries that are available—I'm trying to implement the masking and processing operations myself. What I want to do is the following:

  1. Iterate a 3x3 sliding window over a 256x256 array
  2. At each iteration, I want to perform an operation with a 3x3 image mask (array that consists of fractional values < 1 ) and the 3x3 window from my original array
  3. The operation is that the image mask gets multiplied by the 3x3 window, and that the results get summed up into one number, which represents a weighted average of the original 3x3 area
  4. This sum should get inserted back into the center of the 3x3 window, with the original surrounding values left untouched
  5. However, the output of one of these operations shouldn't be the input of the next operation, so a new array should be created or the original 256x256 array shouldn't be updated until all operations have completed.

The process is sort of like this, except I need to put the result of the convolved feature back into the center of the window it came from: http://ufldl.stanford.edu/wiki/images/6/6c/Convolution_schematic.gif

So, in this above example, the 4 would go back into the center position of the 3x3 window it came from (after all operations had concluded), so it would look like [[1, 1, 1], [0, 4, 1], [0, 0, 1]] and so on for every other convolved feature obtained. A non-referential copy could also be made of the original and this new value inserted into that.

So, this is what I've done so far: I have a 256x256 2D numpy array which is my source image. Using as_strided, I convert it into a 4D numpy array of 3x3 slices. The main problem I'm facing is that I want to execute the operation I've specified over each slice. I'm able to perform it on one slice, but in npsum operations I've tried, it adds up all the slices' results into one value. After this, I either want to create a new 256x256 array with the results, in the fashion that I've described, or iterate over the original, replacing the middle values of each 3x3 window as appropriate. I've tried using ndenumerate to change just the same value (v, x, 1, 1) of my 4D array each time, but since the index returned from my 4D array is of the form (v, x, y, z), I can't seem to figure out how to only iterate through (v, x) and leave the last two parts as constants that shouldn't change at all.

Here's my code thus far:

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

Research from sources like http://wiki.scipy.org/Cookbook/GameOfLifeStrides, http://www.johnvinyard.com/blog/?p=268, and http://chintaksheth.wordpress.com/2013/07/31/numpy-the-tricks-of-the-trade-part-ii/ were very helpful (as well as SO), but they don't seem to address what I'm trying to do exactly (unless I'm missing something obvious). I could probably use a ton of for loops, but I'd rather learn how to do using these awesome Python libraries we have. I also realize I'm combining a few questions together, but that's only because I have the sneaking suspicion that this can all be done very simply! Thanks in advance for any help!

解决方案

When you need to multiply element-wise, then reduce with addition, think np.dot or 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)

这篇关于如何在4D numpy数组上执行迭代2D操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆