2

複数の次元 (x、y、チャネル、z、時間ステップ) の配列があります。ただし、生データは TIFF イメージに (x, y, チャネル) の単一のスタックとして、z * 時間ステップ フレームで格納されます。

最後に、Pillow の Image.getdata() 関数は、再形成が必要な 1D 配列のようなオブジェクトを返します。

データセットが大きすぎてメモリに収まらない場合、これを HDF5 に読み込む最善の方法は何ですか? HDF5に書き込まれた後に配列を再形成すること、または配列に自動的に入力される方法で1Dデータを書き込むことは可能ですか(つまり、xが最速、yが2番目に速いなどで書き込みます)更新:次のようなものnumpy.ndarray.flatが理想的です。

これまでに試したことは次のとおりです(imgはPIL.Image、dsetはh5pyデータセットです):

1) 個々のフレームの読み取り。この方法は、1000 フレームで 300MB に約 20 分かかるため、遅すぎます。ほとんどの時間は dset[] = a 呼び出しに費やされます。

for i in range(0, img_layers):
  img.seek(i)
  a = numpy.array(img.getdata(), dtype=dtype) # a.shape = (sx * sz * channels,)
  a.resize(sx, sy, channels)
  z = i % sz
  frame = i // sz
  dset[..., z, frame] = a

2)不完全:チャンクで読み取ります。これははるかに高速ですが (同じデータセットで 2 分)、4D 画像 (sx、sy、チャネル、時間ステップ) でしか機能せず、z スライスに追加の次元が必要です。

chunk_bits = 256 * 1000**2 # 256MB
frame_bits = depth_bits[dtype] * sx * sy * channels
chunk_frames = chunk_bits // frame_bits
a = numpy.zeros((sx, sy, channels, chunk_frames), dtype=dtype)
for i in range(0, layers):
  img.seek(i)
  temp = numpy.array(img.getdata(), dtype=dtype)
  temp.resize(sx, sy, channels)
  a[..., i % chunk_frames] = temp
  if (i + 1) % chunk_frames == 0 or i == (layers - 1):
    chunk = i // chunk_frames
    dset[..., chunk * chunk_frames : i + 1] = a[..., : i % chunk_frames + 1
4

1 に答える 1

0

選択肢 1 が正解でした。ただし、どの次元が最も速く変化するかによって大きな違いが生じます。

~15 分:

for i in range(0, img_layers):
  img.seek(i)
  a = numpy.array(img.getdata(), dtype=dtype)
  a.resize(sx, sy, channels)
  z = i % sz
  frame = i // sz
  dset[..., z, frame] = a # Majority of time in this call

約 3 分:

for i in range(0, img_layers):
  img.seek(i)
  a = numpy.array(img.getdata(), dtype=dtype) # Majority of time in this call
  a.resize(sx, sy, channels)
  z = i % sz
  frame = i // sz
  dset[frame, z, ...] = a

このデータをすばやく読み取るには、最も速く変化するインデックスを最初ではなく最後にする必要があります。

于 2013-11-19T13:44:40.713 に答える