1

我正在尝试找到将任意形状的 2d numpy 数组下采样为更小(或可能更大)的方形数组的最有效方法 - 我想取每个子数组的最大值并将其放入新数组中。这是我的代码:

import numpy as np

def downSampleMax(inputArray, numFrames):

    newArray = np.zeros([numFrames, numFrames], dtype = np.uint8)
    filterSize = (int(np.ceil(float(inputArray.shape[0]) / numFrames)), 
                  int(np.ceil(float(inputArray.shape[1]) / numFrames)))
    rowArr = np.linspace(0, inputArray.shape[0] - filterSize[0], numFrames, dtype = np.int)
    colArr = np.linspace(0, inputArray.shape[1] - filterSize[1], numFrames, dtype = np.int)

    for iRow in range(numFrames):
        for iCol in range(numFrames):
            newArray[iRow, iCol] = np.max(inputArray[rowArr[iRow]: rowArr[iRow] + filterSize[0], 
                                                     colArr[iCol]: colArr[iCol] + filterSize[1]])

    return newArray 

关于如何显着加快速度的任何想法?我认为从我读过的内容来看,矢量化或切片可能是前进的方向,但不知道该怎么做。

4

1 回答 1

1

这是一种矢量化方法,它以maxNumPythonic 的方式进行逐块查找计算 -

# Get shape of input array
M,N = inArr.shape

# Reshape 2D input array to break it down a 4D array with rows and columns 
# being divided by the number of frames. Then, use `max` along the divided axes.
out = (inArr.reshape(nFrames,M/nFrames,nFrames,N/nFrames)).max(axis=(1,3))

样品运行 -

In [107]: inArr
Out[107]: 
array([[ 37,  47,  35,  96,  84,  55,  36, 218],
       [  4, 199, 104, 246, 136, 123, 215, 237],
       [ 21,  50,  21, 151, 243, 130,  69, 166],
       [242, 233, 161,  57,  20, 122, 189, 120],
       [175,  52, 114, 202,  13, 134,  30,  29],
       [117, 128,  88, 108,  97, 249,  87,  37],
       [246, 237, 230, 166, 157, 215, 254, 219],
       [156,  41,  71,  94, 114, 174, 223,  25]], dtype=uint8)

In [108]: nFrames = 4

In [109]: downSampleMax(inArr, nFrames)
Out[109]: 
array([[199, 246, 136, 237],
       [242, 161, 243, 189],
       [175, 202, 249,  87],
       [246, 230, 215, 254]], dtype=uint8)

In [110]: M,N = inArr.shape

In [111]: (inArr.reshape(nFrames,M/nFrames,nFrames,N/nFrames)).max(axis=(1,3))
Out[111]: 
array([[199, 246, 136, 237],
       [242, 161, 243, 189],
       [175, 202, 249,  87],
       [246, 230, 215, 254]], dtype=uint8)

运行时测试 -

In [112]: inArr = np.random.randint(0,255,(512,512)).astype('uint8')

In [113]: nFrames = 32

In [114]: def vectorized_downSampleMax(inArr, nFrames):
     ...:   M,N = inArr.shape
     ...:   return (inArr.reshape(nFrames,M/nFrames,nFrames,N/nFrames)).max(axis=(1,3))
     ...: 
     ...: 
     ...: def downSampleMax(inArr, nFrames):
     ...: 
     ...:   newArray = np.zeros([nFrames, nFrames], dtype = np.uint8)
     ...:   filterSize = (int(np.ceil(float(inArr.shape[0]) / nFrames)), 
     ...:                 int(np.ceil(float(inArr.shape[1]) / nFrames)))
     ...:   rowArr = np.linspace(0, inArr.shape[0] - filterSize[0], nFrames).astype(int)
     ...:   colArr = np.linspace(0, inArr.shape[1] - filterSize[1], nFrames).astype(int)
     ...: 
     ...:   for iRow in range(nFrames):
     ...:       for iCol in range(nFrames):
     ...:           newArray[iRow, iCol] = np.max(inArr[rowArr[iRow]: rowArr[iRow] + filterSize[0], colArr[iCol]: colArr[iCol] + filterSize[1]])
     ...: 
     ...:   return newArray
     ...: 

In [115]: %timeit downSampleMax(inArr, nFrames)
10 loops, best of 3: 20.1 ms per loop

In [116]: %timeit vectorized_downSampleMax(inArr, nFrames)
1000 loops, best of 3: 909 µs per loop
于 2015-10-04T09:20:51.683 回答