2016-03-19 8 views
1

私はそれぞれが画像を表す3D配列のコレクションを持っています。私は、指定された座標がすべての配列の中で黒でないピクセルを含む出現の回数を探したい。Numpy:インデックスでグループ化された非ゼロ値の出現を見つけよう

result = np.zeros_like(list_of_arrays[0]) 
for array in list_of_arrays: 
    for (y, x) in np.argwhere(array.any(-1)): 
     result[y][x] += 1 
return result 

どのようにしてこの未実装の実装を改善できますか?私が3次元を0または1に変換する方法を知っていたら、各配列をコピーして、それらを追加して自分の答えを得ることができました。問題は、その変換をどのように行うのか分からないことです。 2枚の3x3の写真

# picture 1 
[[[ 208., 208., 208.], 
    [ 0., 0., 0.], 
    [ 110., 110., 110.]], 

[[ 161., 161., 161.], 
    [ 140., 140., 140.], 
    [ 251., 251., 251.]], 

[[ 0., 0., 0.], 
    [ 55., 55., 55.], 
    [ 26., 26., 26.]]] 

# picture 2 
[[[ 88., 88., 88.], 
    [ 140., 140., 140.], 
    [ 0., 0., 0.]], 

[[ 18., 18., 18.], 
    [ 112., 112., 112.], 
    [ 0., 0., 0.]], 

[[ 0., 0., 0.], 
    [ 195., 195., 195.], 
    [ 5., 5., 5.]]] 

# what I'd like 
[[[ 2., 2., 2.], 
    [ 1., 1., 1.], 
    [ 1., 1., 1.]], 

[[ 2., 2., 2.], 
    [ 2., 2., 2.], 
    [ 1., 1., 1.]], 

[[ 0., 0., 0.], 
    [ 2., 2., 2.], 
    [ 2., 2., 2.]]] 
+0

(非常に小さい)入力例を表示できますか? 5x5ピクセルの画像では? –

+0

申し訳ありませんが、最初から追加しておきます。完了しました。 – JBolton

+1

これらの画像は、1つのアレイに格納されているのですか、別のアレイに格納されていますか?単一の場合、それらはどのように格納されますか? '4D'配列または3D配列のリスト? – Divakar

答えて

1

0で表されるので、あなたは黒Falseなり、他のすべての色がTrueなるようarray.astype('bool')を使用してブールする配列を変換することができます。

result = sum(ar.astype('bool') for ar in list_of_arrays) 

データ型変換の代わりに、:各座標における非黒色画素の数で終わるようTrue1になっている間sumとそれらの配列を組み合わせることにより、バック整数に変換しますあなたは、しきい値に画像をnumpy.minimumを使用することができます。

result = sum(np.minimum(ar, 1) for ar in list_of_arrays) 

編集:問題を迅速ケースでは、私はリッテベンチマークを実施しました上記2つのアプローチを比較する:

>>> ar = [np.array([[ 208., 208., 208.], 
     [ 0., 0., 0.], 
     [ 110., 110., 110.]]), np.array([[ 161., 161., 161.], 
     [ 140., 140., 140.], 
     [ 251., 251., 251.]]), np.array([[ 0., 0., 0.], 
     [ 55., 55., 55.], 
     [ 26., 26., 26.]])] 

>>> from time import time 
>>> def f1(arrays): 
...  return sum(np.minimum(a, 1) for a in arrays) 
... 
>>> def f2(arrays): 
...  return sum(a.astype('bool') for a in arrays) 
... 
>>> def f3(arrays): 
...  return (np.array(arrays) != 0).sum(axis=0) 
... 
>>> def timeIt(func): 
...  start = time() 
...  for i in range(1000000): 
...   func(ar) 
...  stop = time() 
...  return stop-start 
... 

>>> timeIt(f1) 
12.203268051147461 
>>> timeIt(f2) 
16.594016790390015 
>>> timeIt(f3) 
18.328339099884033 

結果は画像の数とサイズによって異なる場合があります。

+1

良い点:写真がすでにリストに保存されている場合、リストの理解の方が速いです(1回のトラバーサルが必要ですか?)。つまり、イメージがnumpy配列に格納されている場合、単に 'axis = 0'に沿った合計を使う方が速いです。最初に写真のコレクションを作成するときにOPにデータ構造の選択肢があり、リストの代わりに暗い配列を選択すると、私のアプローチはより効果的だと思います。 – ohruunuruus

+0

あなたは正しいです@ohruunuruus。リストを 'np.array'にキャストするには、高価なデータのコピーが必要です。しかし、画像がどのように格納されているかを制御しているなら、 'np.sum'アプローチも好きです。 – Callidior

2

ため


例は、これら2枚の画像がpic1pic2呼ばnumpyの配列ですと仮定します。

pic1 = np.array(
    [[[ 208., 208., 208.], 
     [ 0., 0., 0.], 
     [ 110., 110., 110.]], 

    [[ 161., 161., 161.], 
     [ 140., 140., 140.], 
     [ 251., 251., 251.]], 

    [[ 0., 0., 0.], 
     [ 55., 55., 55.], 
     [ 26., 26., 26.]]] 
) 

pic2 = np.array(
    [[[ 88., 88., 88.], 
     [ 140., 140., 140.], 
     [ 0., 0., 0.]], 

    [[ 18., 18., 18.], 
     [ 112., 112., 112.], 
     [ 0., 0., 0.]], 

    [[ 0., 0., 0.], 
     [ 195., 195., 195.], 
     [ 5., 5., 5.]]] 
) 

あなたはnp.array([pic1, pic2])でこれらの画像のnumpyの配列を作成することができますかすでに画像がリストにある場合はnp.array(list_of_arrays)です。次に、この4次元配列に論理演算を各要素に個別に適用し、それぞれがゼロでないかどうかを確認します。画像がリストに既にある場合

# Get a numpy array of images 
images = np.array([pic1, pic2]) # or np.array(list_of_arrays) 

# Check for nonzero values and sum along the relevant axis 
result = (images != 0).sum(axis=0) 

array([[[2, 2, 2], 
     [1, 1, 1], 
     [1, 1, 1]], 

     [[2, 2, 2], 
     [2, 2, 2], 
     [1, 1, 1]], 

     [[0, 0, 0], 
     [2, 2, 2], 
     [2, 2, 2]]]) 

は、このアプローチが他ほど高速ではないかもしれない。最後に、axis=0を指定し、得られた4次元アレイを合計します。つまり、画像のコレクションを最初に作成するときにデータ構造を選択し、numpy配列を使用できる場合は、これが最速です。

関連する問題