14

編集私は以下に直面しているより複雑な問題を保持していますが、私の問題はnp.take次のように要約できます。shapeの配列と shapeimg(planes, rows)別の配列があり、それらを使用してshapeの新しい配列を作成するとします。これは、次のようにファンシー インデックスを使用して実現できます。lut(planes, 256)out(planes, rows)out[p,j] = lut[p, img[p, j]]

In [4]: %timeit lut[np.arange(planes).reshape(-1, 1), img]
1000 loops, best of 3: 471 us per loop

しかし、派手なインデックス作成の代わりに、take を使用し、物事に対する python ループをplanes大幅に高速化することができます。

In [6]: %timeit for _ in (lut[j].take(img[j]) for j in xrange(planes)) : pass
10000 loops, best of 3: 59 us per loop

Pythonループなしで操作全体を実行できるように、何らかの方法で再配置できますが、速度の利点を維持するために従来の派手なインデックス作成の代わりに(または代替方法)を使用しlutますか?imgnumpy.take


元の質問 画像で使用したい一連のルックアップ テーブル (LUT) があります。LUT を保持する配列は shape(planes, 256, n)であり、イメージは shape(planes, rows, cols)です。どちらも で、LUT の軸にdtype = 'uint8'一致します。256アイデアは、 LUT の -th プレーンから各 LUTpを介してイメージの -th プレーンを実行することです。np

私のlutimgが次の場合:

planes, rows, cols, n = 3, 4000, 4000, 4
lut = np.random.randint(-2**31, 2**31 - 1,
                        size=(planes * 256 * n // 4,)).view('uint8')
lut = lut.reshape(planes, 256, n)
img = np.random.randint(-2**31, 2**31 - 1,
                    size=(planes * rows * cols // 4,)).view('uint8')
img = img.reshape(planes, rows, cols)

このような派手なインデックス作成を使用した後、私は何を達成できますか

out = lut[np.arange(planes).reshape(-1, 1, 1), img]

これにより、 shape の配列が得られます(planes, rows, cols, n)。ここで、 LUT の -th プレーンの -th LUT を介して実行される-th プレーンがout[i, :, :, j]保持されます...iimgji

これを除いて、すべてが良いです:

In [2]: %timeit lut[np.arange(planes).reshape(-1, 1, 1), img]
1 loops, best of 3: 5.65 s per loop

np.takeこれは完全に受け入れられません。特に、実行速度が大幅に向上するよりも、見栄えの悪い次の代替手段をすべて使用しているためです。

  1. 1 つのプレーンで 1 つの LUT を実行すると、約 70 倍高速に実行されます。

    In [2]: %timeit np.take(lut[0, :, 0], img[0])
    10 loops, best of 3: 78.5 ms per loop
    
  2. 必要なすべての組み合わせを実行する Python ループは、ほぼ 6 倍速く終了します。

    In [2]: %timeit for _ in (np.take(lut[j, :, k], img[j]) for j in xrange(planes) for k in xrange(n)) : pass
    1 loops, best of 3: 947 ms per loop
    
  3. LUT と画像でプレーンのすべての組み合わせを実行してから、planes**2 - planes不要なものを破棄することは、手の込んだインデックス作成よりも高速です。

    In [2]: %timeit np.take(lut, img, axis=1)[np.arange(planes), np.arange(planes)]
    1 loops, best of 3: 3.79 s per loop
    
  4. そして、私が思いついた最速の組み合わせには、プレーンを反復処理する Python ループがあり、x13 をより速く終了します。

    In [2]: %timeit for _ in (np.take(lut[j], img[j], axis=0) for j in xrange(planes)) : pass
    1 loops, best of 3: 434 ms per loop
    

np.takeもちろん問題は、Pythonループなしでこれを行う方法がないかどうかです? 理想的には、必要な再形成またはサイズ変更は、画像ではなく LUT で行われる必要がありますが、私はあなたが思いつくものは何でも受け入れます...

4

1 に答える 1

6

私はあなたの質問が本当に好きだったと言わなければなりません。再配置せずに、LUTまたはIMG次の解決策が機能しました:

%timeit a=np.take(lut, img, axis=1)
# 1 loops, best of 3: 1.93s per loop

しかし、結果から対角線を照会する必要があります: a[0,0], a[1,1], a[2,2]; 欲しいものを手に入れるために。対角要素に対してのみこのインデックス付けを行う方法を見つけようとしましたが、それでもうまくいきませんでした。

LUTおよびを再配置するいくつかの方法をIMG次に示します。 のインデックスIMGが 1 番目のプレーンで 0 ~ 255、2 番目のプレーンで 256 ~ 511、3 番目のプレーンで 512 ~ 767 の場合は次のように機能しますが、それでは次のことができなくなります。'uint8'これは大きな問題になる可能性があります... :

lut2 = lut.reshape(-1,4)
%timeit np.take(lut2,img,axis=0)
# 1 loops, best of 3: 716 ms per loop
# or
%timeit np.take(lut2, img.flatten(), axis=0).reshape(3,4000,4000,4)
# 1 loops, best of 3: 709 ms per loop

私のマシンでは、対角線の評価、つまり、plane1-plane1、plane2-plane2、plane3-plane3 だけが必要なため、ソリューションは依然として最適なオプションであり、非常に適切です。

%timeit for _ in (np.take(lut[j], img[j], axis=0) for j in xrange(planes)) : pass
# 1 loops, best of 3: 677 ms per loop

これにより、より良い解決策についての洞察が得られることを願っています。、およびまたはflatten()と同様の方法で、有望と思われる他のオプションを探すとよいでしょう。np.apply_over_axes()np.apply_along_axis()

以下のコードを使用してデータを生成しました。

import numpy as np
num = 4000
planes, rows, cols, n = 3, num, num, 4
lut = np.random.randint(-2**31, 2**31-1,size=(planes*256*n//4,)).view('uint8')
lut = lut.reshape(planes, 256, n)
img = np.random.randint(-2**31, 2**31-1,size=(planes*rows*cols//4,)).view('uint8')
img = img.reshape(planes, rows, cols)
于 2013-05-09T11:03:05.237 に答える