Мне кажется, что ваша проблема напрямую связана с операциями свертки / максимального объединения.
Недавно я написал наивные подходы к этим операциям, используя только numpy, поэтому я адаптировал один из них (надеюсь) ответьте на свой вопрос.
Вот код:
def rolling_window(input_array, size_kernel, stride, print_dims = True):
"""Function to get rolling windows.
Arguments:
input_array {numpy.array} -- Input, by default it only works with depth equals to 1.
It will be treated as a (height, width) image. If the input have (height, width, channel)
dimensions, it will be rescaled to two-dimension (height, width)
size_kernel {int} -- size of kernel to be applied. Usually 3,5,7. It means that a kernel of (size_kernel, size_kernel) will be applied
to the image.
stride {int or tuple} -- horizontal and vertical displacement
Keyword Arguments:
print_dims {bool} -- [description] (default: {True})
Returns:
[list] -- A list with the resulting numpy.arrays
"""
# Check right input dimension
assert(len(input_array.shape) in set([1,2])), "input_array must have dimension 2 or 3. Yours have dimension {}".format(len(input_array))
if input_array.shape == 3:
input_array = input_array[:,:,0]
# Stride: horizontal and vertical displacement
if isinstance(stride,int):
sh, sw = stride, stride
elif isinstance(stride,tuple):
sh, sw = stride
# Input dimension (height, width)
n_ah, n_aw = input_array.shape
# Filter dimension (or window)
n_k = size_kernel
dim_out_h = int(np.floor( (n_ah - n_k) / sh + 1 ))
dim_out_w = int(np.floor( (n_aw - n_k) / sw + 1 ))
# List to save output arrays
list_tensor = []
# Initialize row position
start_row = 0
for i in range(dim_out_h):
start_col = 0
for j in range(dim_out_w):
# Get one window
sub_array = input_array[start_row:(start_row+n_k), start_col:(start_col+n_k)]
# Append sub_array
list_tensor.append(sub_array)
start_col += sw
start_row += sh
if print_dims:
print("- Input tensor dimensions -- ", input_array.shape)
print("- Kernel dimensions -- ", (n_k, n_k))
print("- Stride (h,w) -- ", (sh, sw))
print("- Total windows -- ", len(list_tensor))
return list_tensor
Чтобы получить непересекающийся прокат windows, вам просто нужно установить stride
и kernel_size
на одно и то же число , Кроме того, это напечатает некоторую информацию и длину найденного windows.
Некоторые примеры:
1) Ваш:
a = np.array([[0, 1, 2, 3, 4, 5],
[6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]], dtype=np.int)
size_kernel = 3 # Or can be set to 3 instead of a tuple
list_tensor = rolling_window(a, size_kernel, stride=3, print_dims = True)
##Output
#- Input tensor dimensions -- (6, 6)
#- Kernel dimensions -- (3, 3)
#- Stride (h,w) -- (3, 3)
#- Total windows -- 4
for array in list_array:
print('\n')
print(array)
## Output
[[ 0 1 2]
[ 6 7 8]
[12 13 14]]
[[ 3 4 5]
[ 9 10 11]
[15 16 17]]
[[18 19 20]
[24 25 26]
[30 31 32]]
[[21 22 23]
[27 28 29]
[33 34 35]]
(Кроме того, по сравнению с вашими результатами я заметил, что ваш код дает вам перекрывающиеся данные, вы можете сравнить второй и четвертый выходы.)
2) массив (5000,5000) с окном (500,500)
%%time
size = 5000
a = np.ones((size,size))
list_tensor = rolling_window(input_array = a, size_kernel = 500, stride=500, print_dims = True)
## Output
#- Input tensor dimensions -- (5000, 5000)
#- Kernel dimensions -- (500, 500)
#- Stride (h,w) -- (500, 500)
#- Total windows -- 100
#CPU times: user 68.7 ms, sys: 115 ms, total: 184 ms
#Wall time: 269 ms
Надеюсь, это поможет!