2011-11-09 2 views
10

numpy.lib.stride_tricks.as_stridedを使用して配列のオーバーラップしていないブロックを反復しようとしていますが、パラメータのドキュメントが見つかりません私は重複ブロックしか得ることができませんでした。Numpy stride_tricksを使用してオーバーラップしない配列ブロックを取得する

たとえば、4x5アレイを4x2x2ブロックから取得したいと考えています。右端と下端の余分なセルが除外されていても問題ありません。

これまでのところ、私のコードは次のとおりです。

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

私の形状や進歩のパラメータが間違っていると思われるので、結果としてブロック配列の形状が正しいように思えるが、最後の2は失敗主張します。オーバーラップしないブロックを得るためにこれらの値をどのように設定する必要がありますか?

答えて

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

2(即ちblocks[0,0,0,1])に到達するために、a1(即ちblocks[0,0,0,0])で開始すると、離れた一つの項目です。 a.itemsizeは(私のマシン上で)4バイトなので、ストライドは1 * 4 = 4です。これにより、最後の値はstrides = (10,2,5,1)*a.itemsize = (40,8,20,4)になります。 6(即ちblocks[0,0,1,0])に到達するために、再び1で開始

は、離れ5(すなわちw)項目ので、ストライドこれはstridesの最後の値に2番目を占める5 * 4 = 20です。 3(即ちblocks[0,1,0,0])に到達するために、再び1で開始

は、離れた2(即ちbw)項目ので、ストライドこれはstridesで第二の値を占め2 * 4 = 8です。

最後に、11(すなわちblocks[1,0,0,0])に到達するために、1始まる、徒歩10(即ちw*bh)項目ので、ストライドは10×4 = 40だからstrides = (40,8,20,4)あります。

+1

ありがとうございました。私たちのa.itemsizeが違うようです(私は8です)。私はあなたのコードを歩みを定義するために(あなたの説明に基づいて)式を使用するようにリファクタリングしたので、誰にとってもうまくいくでしょう。 – Cerin

5

例として、@ unutbuの答えを使用して、私は任意のND配列に対してこのタイリングトリックを実装する関数を作成しました。ソースへのリンクについては以下を参照してください。

>>> 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あなたが必要とするほとんど何を行いview_as_blocks()という名前の関数を持っています。唯一の問題は、ブロックが配列形状に均等に分割されないため、ユースケースを禁じているassertが余分にあることです。しかし、あなたの場合、assertは必要ではないので、function source codeをコピーして、厄介なアサーションを安全に削除することができます。

関連する問題