5

1000以上の配列(同一次元)にわたるピクセル値の平均と標準偏差を計算する必要があるpythonモジュールを書いています。

これを行う最速の方法を探しています。

現在、配列をループ処理し、numpy.dstack を使用して 1000 個の配列をかなり大きな 3D 配列にスタックしています...そして、3 次元 (?) の平均を計算します。各配列の形状は (5000,4000) です。

このアプローチにはかなりの時間がかかります。

この問題に取り組むためのより効率的な方法についてアドバイスできる人はいますか?

4

3 に答える 3

2

たぶん、次のような累積的な方法で計算できます(テストされていmeanません):std

im_size = (5000,4000)

cum_sum = np.zeros(im_size)
cum_sum_of_squares = np.zeros(im_size)
n = 0

for filename in filenames:
    image = read_your_image(filename)
    cum_sum += image
    cum_sum_of_squares += image**2
    n += 1

mean_image = cum_sum / n
std_image = np.sqrt(cum_sum_of_squares / n - (mean_image)**2)

これはおそらく、ディスクから画像を読み取る速度によって制限されます。メモリには一度に 1 つのイメージしかないため、メモリによって制限されることはありません。この方法での の計算はstd、2 つの大きな数を減算する可能性があるため、数値的な問題が発生する可能性があります。それが問題である場合は、ファイルを 2 回ループする必要があります。最初に平均を計算し、次に(image - mean_image)**22 回目のパスで累積します。

于 2013-08-29T21:15:47.473 に答える
1

事前に割り当てて埋めます。これにより、実行時のフォームが約 1000 秒から 20 秒に短縮されました

data_stack = numpy.empty((321, 720, 1000), dtype=numpy.float32)
for index in range(len(data)):
  data_stack[0:321,0:720,index] = data[index]

私は似たようなことをしていました。dstack は、この問題の適切な解決策ではありません。同僚が動的配列問題と償却分析を思い出させてくれました。 http://anh.cs.luc.edu/363/notes/06A_Amortizing.html

動的配列を拡張する場合は、元のデータと新しいデータを保持できる新しい配列を割り当てる必要があります。次に、古い配列を新しい配列にコピーし、新しいデータを新しい配列にコピーします。それは高価な操作です。

サイズ 10 の配列があり、一度に 2 つの項目を 1 つずつ追加するとします。最初のアイテムを追加するには、配列をサイズ 11 に拡張し、11 個のアイテム (元の 10 + 1 個の新しいアイテム) をコピーする必要があります。2 番目のアイテムを追加するには、配列をサイズ 12 に拡張し、12 個のアイテムをコピーする必要があります。2 つの項目を追加することが前もってわかっていれば、最初に配列のサイズを 12 に変更し、合計 23 項目ではなく 12 項目のみをコピーすることができます。より効率的なソリューションです。

これがどのように適用されるか: dstack は ndarray のサイズを 2 倍にするのではなく、必要な量のメモリのみを割り当てることを意図しています。したがって、dstack を呼び出すたびに、ndarray にあるすべてのデータを、新しいデータ用のスペースを持つ新しい ndarray にコピーします。呼び出しごとに dstack の時間が増加することに注意してください。

于 2013-09-13T19:52:59.650 に答える