本文介绍了带有滑动窗口的总和真的很慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码:

shape = np.array([6, 6])
grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i, x in enumerate(shape)], indexing='ij')]).T
slices = [tuple(slice(box[i], box[i] + 2) for i in range(len(box))) for box in grid]
score = np.zeros((7,7,3))
column = np.random.randn(36, 12) #just for example

column
>> array([[  0,   1,   2,   3, ... 425, 426, 427, 428, 429, 430, 431]])

column = column.reshape((16, 3, 3, 3))
for i, window in enumerate(slices):
        score[window] += column[i]
score
>> array([[[0.000e+00, 1.000e+00, 2.000e+00],
    [3.000e+01, 3.200e+01, 3.400e+01],
    [9.000e+01, 9.300e+01, 9.600e+01], ...
    [8.280e+02, 8.300e+02, 8.320e+02],
    [4.290e+02, 4.300e+02, 4.310e+02]]])

它可以工作,但是最后两行要花很多时间,因为它们会循环播放.问题是"grid"变量包含一个窗口数组.而且我现在不知道如何加快这一过程.

It works but last 2 lines take really much time as they will be in loop. The problem is that 'grid' variable contains an array of windows. And I don't now how to speed up the process.

推荐答案

让我们从根本上简化问题-减小尺寸,并减小最终尺寸3尺寸:

Let's simplify the problem at bit - reduce the dimensions, and drop the final size 3 dimension:

In [265]: shape = np.array([4,4])
In [266]: grid = np.array([x.ravel() for x in np.meshgrid(*[np.arange(x) for i
     ...: , x in enumerate(shape)], indexing='ij')]).T
     ...: grid = [tuple(slice(box[i], box[i] + 3) for i in range(len(box))) fo
     ...: r box in grid]
     ...:
     ...:
In [267]: len(grid)
Out[267]: 16
In [268]: score = np.arange(36).reshape(6,6)
In [269]: X = np.array([score[x] for x in grid]).reshape(4,4,3,3)
In [270]: X
Out[270]:
array([[[[ 0,  1,  2],
         [ 6,  7,  8],
         [12, 13, 14]],

        [[ 1,  2,  3],
         [ 7,  8,  9],
         [13, 14, 15]],

        [[ 2,  3,  4],
         [ 8,  9, 10],
         [14, 15, 16]],

        ....
        [[21, 22, 23],
         [27, 28, 29],
         [33, 34, 35]]]])

这是一个移动窗口-一个(3,3)数组,移1,...,移1,等等

This is a moving window - one (3,3) array, shift over 1,..., shift down 1, etc

使用as_strided可以构造由所有这些窗口组成的数组视图,但实际上无需复制值.在与as_strided一起工作之前,我就可以构建如下等效的步幅:

With as_strided is is possible to construct a view of the array, that consists of all these windows, but without actually copying values. Having worked with as_strided before I was able construct the equivalent strides as:

In [271]: score.shape
Out[271]: (6, 6)
In [272]: score.strides
Out[272]: (48, 8)
In [273]: ast = np.lib.stride_tricks.as_strided
In [274]: x=ast(score, shape=(4,4,3,3), strides=(48,8,48,8))
In [275]: np.allclose(X,x)
Out[275]: True

这可以扩展到您的(28,28,3)维度,并变成总和.

This could be extended to your (28,28,3) dimensions, and turned into the summation.

生成此类移动窗口已在先前的SO问题中进行了介绍.而且还可以在其中一个图像处理程序包中实现.

Generating such moving windows has been covered in previous SO questions. And it's also implemented in one of the image processing packages.

适应3通道图像

In [45]: arr.shape
Out[45]: (6, 6, 3)
In [46]: arr.strides
Out[46]: (144, 24, 8)
In [47]: arr[:3,:3,0]
Out[47]:
array([[ 0.,  1.,  2.],
       [ 6.,  7.,  8.],
       [12., 13., 14.]])

In [48]: x = ast(arr, shape=(4,4,3,3,3), strides=(144,24,144,24,8))
In [49]: x[0,0,:,:,0]
Out[49]:
array([[ 0.,  1.,  2.],
       [ 6.,  7.,  8.],
       [12., 13., 14.]])

由于我们一次将窗口移动一个元素,所以x的步幅很容易从源步幅导出.

Since we are moving the window by one element at a time, the strides for x are easily derived form the source strides.

对于4x4窗口,只需更改形状

For 4x4 windows, just change the shape

x = ast(arr, shape=(3,3,4,4,3), strides=(144,24,144,24,8))


>有效地使用多个小块切片进行随机图像裁剪

@Divikar建议使用skimage

@Divikar suggests using skimage

使用默认的step=1,结果兼容:

With the default step=1, the result is compatible:

In [55]: from skimage.util.shape import view_as_windows
In [63]: y = view_as_windows(arr,(4,4,3))
In [64]: y.shape
Out[64]: (3, 3, 1, 4, 4, 3)
In [69]: np.allclose(x,y[:,:,0])
Out[69]: True

这篇关于带有滑动窗口的总和真的很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 11:58