ラスター(実際にはUSGS DEM)があり、下の画像のように小さなチャンクに分割する必要があります。これは、ArcGIS 10.0でSplit Rasterツールを使用して実現されました。これを行うにはFOSSメソッドが必要です。私はGDALを見て、確かにそれを行うと考えています(何らかの方法でgdal_translateで)が、何も見つかりません。最終的には、ラスターを取得して、どのくらいの大きさ(4KM x 4KMチャンク)に分割したいかを伝えたいと思います。
ラスター(実際にはUSGS DEM)があり、下の画像のように小さなチャンクに分割する必要があります。これは、ArcGIS 10.0でSplit Rasterツールを使用して実現されました。これを行うにはFOSSメソッドが必要です。私はGDALを見て、確かにそれを行うと考えています(何らかの方法でgdal_translateで)が、何も見つかりません。最終的には、ラスターを取得して、どのくらいの大きさ(4KM x 4KMチャンク)に分割したいかを伝えたいと思います。
回答:
gdal_translateは、-srcwinまたは-projwinオプションを使用して機能します。
-srcwin xoff yoff xsize ysize:ピクセル/ラインの位置に基づいて、コピーするソース画像からサブウィンドウを選択します。
-projwin ulx uly lrx lry:コピーするソースイメージからサブウィンドウを選択します(-srcwinなど)が、ジオリファレンス座標で指定されたコーナーを使用します。
ピクセル/ラインの位置またはコーナー座標を考え出し、gdal_translateで値をループする必要があります。ピクセル値を使用して-srcwinが適している場合、以下の高速で汚れたpythonのようなものが機能しますが、座標で整理するにはもう少し作業が必要になります。
import os, gdal
from gdalconst import *
width = 512
height = 512
tilesize = 64
for i in range(0, width, tilesize):
for j in range(0, height, tilesize):
gdaltranString = "gdal_translate -of GTIFF -srcwin "+str(i)+", "+str(j)+", "+str(tilesize)+", " \
+str(tilesize)+" utm.tif utm_"+str(i)+"_"+str(j)+".tif"
os.system(gdaltranString)
@wwnickのソリューションに基づく私のソリューションは、ファイル自体からラスターディメンションを読み取り、必要に応じてエッジタイルを小さくすることで画像全体をカバーします。
import os, sys
from osgeo import gdal
dset = gdal.Open(sys.argv[1])
width = dset.RasterXSize
height = dset.RasterYSize
print width, 'x', height
tilesize = 5000
for i in range(0, width, tilesize):
for j in range(0, height, tilesize):
w = min(i+tilesize, width) - i
h = min(j+tilesize, height) - j
gdaltranString = "gdal_translate -of GTIFF -srcwin "+str(i)+", "+str(j)+", "+str(w)+", " \
+str(h)+" " + sys.argv[1] + " " + sys.argv[2] + "_"+str(i)+"_"+str(j)+".tif"
os.system(gdaltranString)
ラスターのリタイル専用のバンドルされたpythonスクリプトgdal_retileがあります。
gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeight]
[-overlap val_in_pixel]
[-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
CInt16/CInt32/CFloat32/CFloat64}]'
[ -tileIndex tileIndexName [-tileIndexField tileIndexFieldName]]
[ -csv fileName [-csvDelim delimiter]]
[-s_srs srs_def] [-pyramidOnly]
[-r {near/bilinear/cubic/cubicspline/lanczos}]
-levels numberoflevels
[-useDirForEachRow]
-targetDir TileDirectory input_files
例えば:
gdal_retile.py -ps 512 512 -targetDir C:\example\dir some_dem.tif
尋ねた@Aaronの場合:
拡張マルチコアおよびマルチスレッド操作のために-multiオプションを使用する@wwnickの答えのgdalwarpバージョンを見つけたい
わずかな免責事項
これはを使用しますがgdalwarp
、パフォーマンスが大幅に向上すると確信しているわけではありません。これまでI / Oに縛られてきました-このスクリプトを大きなラスターで実行して多くの小さな部分に分割すると、CPUに負荷がかかりそうにないため、ボトルネックはディスクへの書き込みであると考えられます。タイルなどを同時に再投影することを計画している場合、これは変わる可能性があります。ここにチューニングのヒントがあります。短いプレイで改善されたわけではなく、CPUが制限要因になることはありませんでした。
免責事項は別としてgdalwarp
、ラスターをいくつかの小さなタイルに分割するために使用するスクリプトを次に示します。フロア分割のためにいくらかの損失があるかもしれませんが、これはあなたが望むタイルの数を選ぶことによって世話をすることができます。それは次のようになりますn+1
どこn
あなたが取得することにより、分割数であるtile_width
とtile_height
変数が。
import subprocess
import gdal
import sys
def gdalwarp(*args):
return subprocess.check_call(['gdalwarp'] + list(args))
src_path = sys.argv[1]
ds = gdal.Open(src_path)
try:
out_base = sys.argv[2]
except IndexError:
out_base = '/tmp/test_'
gt = ds.GetGeoTransform()
width_px = ds.RasterXSize
height_px = ds.RasterYSize
# Get coords for lower left corner
xmin = int(gt[0])
xmax = int(gt[0] + (gt[1] * width_px))
# get coords for upper right corner
if gt[5] > 0:
ymin = int(gt[3] - (gt[5] * height_px))
else:
ymin = int(gt[3] + (gt[5] * height_px))
ymax = int(gt[3])
# split height and width into four - i.e. this will produce 25 tiles
tile_width = (xmax - xmin) // 4
tile_height = (ymax - ymin) // 4
for x in range(xmin, xmax, tile_width):
for y in range(ymin, ymax, tile_height):
gdalwarp('-te', str(x), str(y), str(x + tile_width),
str(y + tile_height), '-multi', '-wo', 'NUM_THREADS=ALL_CPUS',
'-wm', '500', src_path, out_base + '{}_{}.tif'.format(x, y))
GRASS GISのr.tileを使用できます。r.tileは、ユーザー定義のプレフィックスに基づいて番号付きのマップ名を使用して、タイルごとに個別のラスタマップを生成します。タイルの幅(列)とタイルの高さ(行)を定義できます。
Grass -Session Python API を使用すると、外部からr.tile機能を呼び出す、つまりスタンドアロンスクリプトを記述するのに必要なPythonコードは数行だけです。r.externalおよびr.external.outを使用しても、GRASS GIS処理ステップ中にデータの重複は発生しません。
擬似コード: