web-dev-qa-db-ja.com

numpy:配列型をすばやく変換する方法

Numpy配列のastype()メソッドはあまり効率的ではないことがわかりました。 300万のUint8ポイントを含む配列があります。これに3x3行列を掛けるには2秒かかりますが、結果をuint16からuint8に変換するにはさらに1秒かかります。

より正確に :

    print time.clock()
    imgarray = np.dot(imgarray,  M)/255
    print time.clock()
    imgarray = imgarray.clip(0, 255)
    print time.clock()
    imgarray = imgarray.astype('B')
    print time.clock()

内積とスケーリングには2秒かかります
クリッピングには200ミリ秒かかります型変換には1秒かかります

他の操作にかかる時間を考えると、astypeの方が速いと思います。型変換を行うためのより速い方法はありますか、それとも型変換がそれほど難しくないはずだと推測するときに私は間違っていますか?

編集:目標は、最後の8ビット配列をファイルに保存することです

15
shodanex

imgarray = imgarray.astype('B')を使用すると、配列のコピーを取得し、指定した型にキャストします。新しく割り当てられた配列を指すようにimgarrayをすぐに反転した場合でも、これには追加のメモリ割り当てが必要です。

imgarray.view('uint8')を使用すると、配列のビューが表示されます。これは、_uint8_ではなく_imgarray.dtype_として解釈されることを除いて、同じデータを使用します。 (_np.dot_は_uint32_配列を返すため、_np.dot_の後、imgarrayは_uint32_型になります。)

ただし、viewを使用する場合の問題は、32ビット整数が4つの8ビット整数として表示され、最後の8ビットの値のみが考慮されることです。したがって、4番目ごとの8ビット整数にスキップする必要があります。スライスすることでそれを行うことができます:

imgarray.view('uint8')[:,::4]

IPythonの%timeitコマンドは、次の方法で処理が大幅に高速化されることを示しています。

_In [37]: %timeit imgarray2 = imgarray.astype('B')
10000 loops, best of 3: 107 us per loop

In [39]: %timeit imgarray3 = imgarray.view('B')[:,::4]
100000 loops, best of 3: 3.64 us per loop
_
25
unutbu