ディレクトリからnumpyの配列に画像を読み込むための最も速いアプローチを見つけようとしています。私の最終目標は、これらのすべての画像からのピクセルの最大、最小、およびn番目のパーセンタイルなどの統計を計算することです。 .max
と.min
などの組み込み配列メソッドとnp.percentile
関数を使用できるので、すべての画像のピクセルが1つの大きな数値配列にあるときは、これは簡単で高速です。何千枚もの画像を1つの大きなnumpyの配列に読み込む最も速いアプローチ
以下は、25枚のTIFF画像(512x512ピクセル)のタイミング例です。これらのベンチマークは、ジュピターノートで%%timit
を使用したものです。その違いはあまりにも小さいので、わずか25枚の画像には実用上の意味がありませんが、私は将来何千枚もの画像を読むつもりです。上記のリストと辞書アプローチ辞書
%%timeit
imgs = {}
img_path = '/path/to/imgs/'
for img in os.listdir(img_path):
imgs[num] = io.imread(os.path.join(img_path, img))
## 33.3 ms ± 402 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
を使用してリスト
%%timeit
imgs = []
img_path = '/path/to/imgs/'
for img in os.listdir(img_path):
imgs.append(io.imread(os.path.join(img_path, img)))
## 32.2 ms ± 355 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
への追加
# Imports
import os
import skimage.io as io
import numpy as np
は、私はループを交換しようとしましたsimによるそれぞれの理解結果は時間的に似ています。また、辞書キーを事前に割り当ててみましたが、時間に大きな違いはありませんでした。リストから大きな配列に画像を取得するには、
np.concatenate(imgs)
を使用します。これには〜1 msしかかかりません。最初の次元Iが最初に考え%%timeit imgs = np.ndarray((512*25,512), dtype='uint16') img_path = '/path/to/imgs/' for num, img in enumerate(os.listdir(img_path)): imgs[num*512:(num+1)*512, :] = io.imread(os.path.join(img_path, img)) ## 33.5 ms ± 804 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
第三の次元に沿ってnumpyのを事前割当て
%%timeit imgs = np.ndarray((512,512,25), dtype='uint16') img_path = '/path/to/imgs/' for num, img in enumerate(os.listdir(img_path)): imgs[:, :, num] = io.imread(os.path.join(img_path, img)) ## 71.2 ms ± 2.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
沿ってnumpyの配列を事前割当て
ループ内に動的変数展開がないので、numpyの事前割り振り手法は高速になりますが、そうではありません。最も直感的なアプローチは最後のものです。各イメージは配列の3番目の軸に沿って別々の次元を占めますが、これも最も遅いです。取られた追加の時間は、事前割り振り自体に起因するものではなく、約1msしかかかりません。
I持ってこれに関する3つの質問:
- なぜnumpyの事前割り当ては、辞書とリストのソリューションよりも速くない近づいているのですか?
- 何千もの画像を1つの大量の配列に読み込む最速の方法はどれですか?
- numpyやscikit-imageの外側を見ると、イメージを読み込むためのさらに高速なモジュールが得られるでしょうか?私は
plt.imread()
を試しましたが、scikit-image.io
モジュールは高速です。
'(25、512、512)'の配列を初期化しようとしましたか?最初の次元は外側の次元です。最初のリストアプローチからの 'np.array(imgs)'はこの形を作り出します。その33msの大部分は、ストレージではなく負荷です。それをテストするには、配列を累積することなくロードを試みてください。 – hpaulj
ありがとう@hpaulj!あなたの外の寸法についてのヒントと、私の費やした時間のほとんどが頭上からのものであることが役立っていました。私は300の高解像度のTIFF(1024x1024ピクセル)を試して、numpyの外側の次元のアプローチ([300、1024、1024]または[1024,300,1024]のいずれか)が今や最速(〜1秒)です。 2番目はリストと辞書の解(〜1.7s)で、numpyの内部(?)の次元[1024,1024,300]は最後に死んでいます(〜4.6s)。回答を追加すると、これらのベンチマークを追加して受け入れることができます。 –
@hpauljリンクを追加して、最初の(そして2番目の)次元が外側の次元であることをもう少し詳しく説明すると、本当にありがたいです。私は検索に関連するものは見つけられません。 –