2011-11-09 10 views
10

Próbuję użyć numpy.lib.stride_tricks.as_strided do iterowania nad nienakładającymi się blokami tablicy, ale mam problem ze znalezieniem dokumentacji parametrów, więc Mogłem tylko nakładać się na bloki.Używanie Numpy stride_tricks do uzyskania nienakładających się bloków tablicowych

Na przykład mam tablicę 4x5, z której chciałbym otrzymać 4 bloki 2x2. Nie mam nic przeciwko dodatkowym komórkom po prawej i dolnej krawędzi.

tej pory mój kod to:

import sys 
import numpy as np 

a = np.array([ 
[1,2,3,4,5], 
[6,7,8,9,10], 
[11,12,13,14,15], 
[16,17,18,19,20], 
]) 

sz = a.itemsize 
h,w = a.shape 
bh,bw = 2,2 

shape = (h/bh, w/bw, bh, bw) 
strides = (w*sz, sz, w*sz, sz) 
blocks = np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides) 

print blocks[0][0] 
assert blocks[0][0].tolist() == [[1, 2], [6,7]] 
print blocks[0][1] 
assert blocks[0][1].tolist() == [[3,4], [8,9]] 
print blocks[1][0] 
assert blocks[1][0].tolist() == [[11, 12], [16, 17]] 

Kształt otrzymanej tablicy bloków wydaje się być poprawne, ale dwa ostatnie nie twierdzi, przypuszczalnie dlatego, że moje parametry kształtu lub postępy są nieprawidłowe. Jakie wartości należy ustawić, aby uzyskać nie nakładające się bloki?

Odpowiedz

12
import numpy as np 
n=4 
m=5 
a = np.arange(1,n*m+1).reshape(n,m) 
print(a) 
# [[ 1 2 3 4 5] 
# [ 6 7 8 9 10] 
# [11 12 13 14 15] 
# [16 17 18 19 20]] 
sz = a.itemsize 
h,w = a.shape 
bh,bw = 2,2 
shape = (h/bh, w/bw, bh, bw) 
print(shape) 
# (2, 2, 2, 2) 

strides = sz*np.array([w*bh,bw,w,1]) 
print(strides) 
# [40 8 20 4] 

blocks=np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides) 
print(blocks) 
# [[[[ 1 2] 
# [ 6 7]] 
# [[ 3 4] 
# [ 8 9]]] 
# [[[11 12] 
# [16 17]] 
# [[13 14] 
# [18 19]]]] 

Począwszy od 1 w a (tj blocks[0,0,0,0]), aby dostać się do 2 (tj blocks[0,0,0,1]) stanowi jeden element z dala. Ponieważ (na moim komputerze) a.itemsize ma 4 bajty, krok to 1 * 4 = 4. Daje nam to ostatnią wartość w strides = (10,2,5,1)*a.itemsize = (40,8,20,4).

Już znowu 1, aby dostać się do 6 (tj blocks[0,0,1,0]) jest 5 (tj w) pozycje z dala, więc krok jest 5 * 4 = 20. Stanowi to drugie do ostatniej wartości w strides.

Począwszy od 1 jeszcze raz, aby dostać się do 3 (tj blocks[0,1,0,0]), wynosi 2 (tj bw) pozycje z dala, więc krok jest 2 * 4 = 8. Stanowi to dla drugiej wartości strides.

Wreszcie, począwszy od 1, aby dostać się do 11 (tj blocks[1,0,0,0]), wynosi 10 (tj w*bh) pozycje z dala, więc krok jest 10 * 4 = 40. Więc strides = (40,8,20,4).

+1

Dzięki. Wygląda na to, że nasza a.itemsize różni się (moja to 8). Przetłumaczyłem Twój kod, aby użyć formuły (w oparciu o twoje wyjaśnienie), aby zdefiniować kroki, więc będzie działać dla wszystkich. – Cerin

5

Używając odpowiedzi @ unutbu jako przykładu, napisałem funkcję, która implementuje tę sztuczkę do kafelkowania dla dowolnej tablicy ND. Zobacz poniżej link do źródła.

>>> a = numpy.arange(1,21).reshape(4,5) 

>>> print a 
[[ 1 2 3 4 5] 
[ 6 7 8 9 10] 
[11 12 13 14 15] 
[16 17 18 19 20]] 

>>> blocks = blockwise_view(a, blockshape=(2,2), require_aligned_blocks=False) 

>>> print blocks 
[[[[ 1 2] 
    [ 6 7]] 

    [[ 3 4] 
    [ 8 9]]] 


[[[11 12] 
    [16 17]] 

    [[13 14] 
    [18 19]]]] 

[blockwise_view.py][test_blockwise_view.py]

1

scikit-image posiada funkcję o nazwie view_as_blocks() że robi prawie co trzeba. Jedynym problemem jest to, że ma dodatkowy assert, który zabrania użycia twojego przypadku, ponieważ twoje bloki nie dzielą się równomiernie na kształt tablicy. Ale w twoim przypadku assert nie jest konieczne, więc możesz skopiować function source code i bezpiecznie usunąć brzydkie stwierdzenie siebie.

Powiązane problemy