sの多数の配列に格納されたuint8
形状の画像があり(planes, rows, cols)
ます。uint8
これを、 sの形状のマスクに格納されている値と比較する必要があります(mask_rows, mask_cols)
。画像は非常に大きい場合がありますが、マスクは通常小さく、通常(256, 256)
は上に並べて表示されimage
ます。コードを単純化するために、そのふりをしてみましょrows = 100 * mask_rows
うcols = 100 * mask_cols
。
私が現在このしきい値を処理している方法は、次のようなものです。
out = image >= np.tile(mask, (image.shape[0], 100, 100))
で顔を平手打ちする前にこの方法で処理できる最大の配列MemoryError
は、より少し大きいです(3, 11100, 11100)
。私がそれを理解した方法で、このように物事を行うと、メモリ内に最大3つの巨大な配列が共存します:image
、タイルmask
、およびリターンout
。しかし、タイル状のマスクは、10,000回以上コピーされた同じ小さな配列です。したがって、そのメモリを節約できれば、メモリの2/3しか使用せず、3/2大きい画像を処理できるはずなので、サイズは約(3, 13600, 13600)
です。ちなみに、これは、しきい値処理を適切に実行した場合に得られるものと一致しています。
np.greater_equal(image, (image.shape[0], 100, 100), out=image)
より大きな配列を処理するための周期的な性質を利用する私の(失敗した)試みは、周期的な線形配列でmask
インデックスを付けることでした:mask
mask = mask[None, ...]
rows = np.tile(np.arange(mask.shape[1], (100,))).reshape(1, -1, 1)
cols = np.tile(np.arange(mask.shape[2], (100,))).reshape(1, 1, -1)
out = image >= mask[:, rows, cols]
小さなアレイの場合、20倍の速度低下(!!!)がありますが、他のアレイと同じ結果が得られますが、大きなサイズでは実行に失敗します。代わりにMemoryError
、他のメソッドが問題なく処理する値に対しても、最終的にpythonをクラッシュさせます。
私が起こっていると思うのは、numpyが実際(planes, rows, cols)
にインデックスを作成する配列を構築してmask
いるため、メモリを節約できないだけでなく、int32
sの配列であるため、実際に格納するのに4倍のスペースが必要です...
これについてどうやって行くかについてのアイデアはありますか?トラブルを回避するために、以下のサンドボックスコードを試してみてください。
import numpy as np
def halftone_1(image, mask) :
return np.greater_equal(image, np.tile(mask, (image.shape[0], 100, 100)))
def halftone_2(image, mask) :
mask = mask[None, ...]
rows = np.tile(np.arange(mask.shape[1]),
(100,)).reshape(1, -1, 1)
cols = np.tile(np.arange(mask.shape[2]),
(100,)).reshape(1, 1, -1)
return np.greater_equal(image, mask[:, rows, cols])
rows, cols, planes = 6000, 6000, 3
image = np.random.randint(-2**31, 2**31 - 1, size=(planes * rows * cols // 4))
image = image.view(dtype='uint8').reshape(planes, rows, cols)
mask = np.random.randint(256,
size=(1, rows // 100, cols // 100)).astype('uint8')
#np.all(halftone_1(image, mask) == halftone_2(image, mask))
#halftone_1(image, mask)
#halftone_2(image, mask)
import timeit
print timeit.timeit('halftone_1(image, mask)',
'from __main__ import halftone_1, image, mask',
number=1)
print timeit.timeit('halftone_2(image, mask)',
'from __main__ import halftone_2, image, mask',
number=1)