GDALオープンソースライブラリとそのライブラリで提供されるコマンドラインユーティリティを使用して、画像をタイリングするためのPythonスクリプトを作成しました。まず、各タイル範囲を示す入力データセットを読み取ります。次に、タイルをループし、サブプロセスを開始してgdalwarpを呼び出し、入力画像をループ内の現在のタイルにクリップします。
Popen.wait()を使用しないのは、タイルが同時に処理されないようにするためですが、サブプロセスによって返されたメッセージを追跡したいのです。さらに、特定のタイルの作成が完了したら、gdalinfoを使用して新しいファイルの統計を計算する必要があります。これには、別のサブプロセスが必要です。
コードは次のとおりです。
processing = {}
for tile in tileNums:
subp = subprocess.Popen(['gdalwarp', '-ot', 'Int16', '-r', 'cubic', '-of', 'HFA', '-cutline', tileIndexShp, '-cl', os.path.splitext(os.path.basename(tileIndexShp))[0], '-cwhere', "%s = '%s'" % (tileNumField, tile), '-crop_to_cutline', os.path.join(inputTileDir, 'mosaic_Proj.vrt'), os.path.join(outputTileDir, "Tile_%s.img" % regex.sub('_', tile))], stdout=subprocess.PIPE)
processing[tile] = [subp]
while processing:
for tile, subps in processing.items():
for idx, subp in enumerate(subps):
if subp == None: continue
poll = subp.poll()
if poll == None: continue
elif poll != 0:
subps[idx] = None
print tile, "%s Unsuccessful" % ("Retile" if idx == 0 else "Statistics")
else:
subps[idx] = None
print tile, "%s Succeeded" % ("Retile" if idx == 0 else "Statistics")
if subps == [None, None]:
del processing[tile]
continue
subps.append(subprocess.Popen(['gdalinfo', '-stats', os.path.join(outputTileDir, "Tile_%s.img" % regex.sub('_',tile))], stdout=subprocess.PIPE))
ほとんどの場合、これは私にとってはうまくいきますが、私が見ている1つの問題は、最後のタイルに到達したときに無限ループを作成しているように見えることです。これが最善の方法ではないことはわかっていますが、私はサブプロセスモジュールに非常に慣れていないので、基本的にこれを一緒に投げて動作させようとしました。
タイルのリストをループし、同時に処理できるタイルごとにサブプロセスを生成し、タイルごとに最初のサブプロセスが完了したときに2番目のサブプロセスを生成するためのより良い方法を誰かが推奨できますか?
更新: これまでのすべてのアドバイスに感謝します。マルチプロセッシングモジュールとプールを利用するために、上記のコードをリファクタリングしようとしました。
新しいコードは次のとおりです。
def ProcessTile(tile):
tileName = os.path.join(outputTileDir, "Tile_%s.img" % regex.sub('_', tile))
warp = subprocess.Popen(['gdalwarp', '-ot', 'Int16', '-r', 'cubic', '-of', 'HFA', '-cutline', tileIndexShp, '-cl', os.path.splitext(os.path.basename(tileIndexShp))[0], '-cwhere', "%s = '%s'" % (tileNumField, tile), '-crop_to_cutline', os.path.join(inputTileDir, 'mosaic_Proj.vrt'), tileName], stdout=subprocess.PIPE)
warpMsg = tile, "Retile %s" % "Successful" if warp.wait() == 0 else "Unsuccessful"
info = subprocess.Popen(['gdalinfo', '-stats', tileName], stdout=subprocess.PIPE)
statsMsg = tile, "Statistics %s" % "Successful" if info.wait() == 0 else "Unsuccessful"
return warpMsg, statsMsg
print "Retiling..."
pool = multiprocessing.Pool()
for warpMsg, statsMsg in pool.imap_unordered(ProcessTile, tileNums): print "%s\n%s" % (warpMsg, statsMsg)
これは私にとっていくつかの大きな問題を引き起こしています。まず第一に、私は多くの新しいプロセスが作成されることになります。約半分はpython.exeで、残りの半分は、別のタイリングスキーム(gdalbuildvrt.exe)で既にタイリングされている場合に、受信画像をモザイク化するために上記のコードの前に呼び出す別のgdalユーティリティです。作成されているすべてのpython.exeプロセスとgdalbuildvrt.exeプロセスの間で、CPUの約25%(ハイパースレッドの場合は8コアのIntel I7)と16 GBのRAMの99%が使用され、コンピューターが完全にハングします。タスクマネージャーで、またはtaskkillを使用してコマンドラインからプロセスを強制終了することもできません。
ここで何が欠けていますか?