GDALを使用してラスターを小さなチャンクに分割しますか?


18

ラスター(実際にはUSGS DEM)があり、下の画像のように小さなチャンクに分割する必要があります。これは、ArcGIS 10.0でSplit Rasterツールを使用して実現されました。これを行うにはFOSSメソッドが必要です。私はGDALを見て、確かにそれを行うと考えています(何らかの方法でgdal_translateで)が、何も見つかりません。最終的には、ラスターを取得して、どのくらいの大きさ(4KM x 4KMチャンク)に分割したいかを伝えたいと思います。

ここに画像の説明を入力してください


subprocess.Popenを使用して複数のgdal変換を同時に実行するユーティリティがあり、フィッシュネットを使用して大きなラスターをタイルに抽出するために使用します。特に、入力および/または出力が高度に圧縮されている場合)、どちらも高度に圧縮されていない場合、プロセスはHDDアクセスでピークに達し、一度に1つ実行するよりもはるかに高速ではありません。残念ながら、厳密な命名規則のために共有するには十分ではありませんが、とにかく考えの糧です。GDALWarpの-multiオプションは多くの場合問題を引き起こし、利用できない2つのスレッド(1つの読み取り、1つの書き込み)のみを使用します。
マイケルスティムソン

回答:


18

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)

1
こんにちは、ジオティフ画像で-projwinオプションを試してみると、「警告:計算された-srcwin -3005000 1879300 50 650は完全にラスター範囲外になります。しかし、続行します」という警告が表示されます。ジオリファレンス座標を使用します。
ncelik

@ncelikは、おそらくprojwinでセル座標を使用しているため、代わりにsrcwinを使用する必要があるためです。問題が発生した場合は、関連するすべての情報を含む新しい質問を投稿してください。特定の問題に関する提案を行うことができます。
マイケルスティムソン

15

@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)

sys.argv [2]と書かれているsys.argv [1]にすべきだと思いますか?
オスカーリン

3
sys.argv [2]は、出力ファイルのプレフィックスとして使用されると思います。とても助かりました-@Riesに感謝します!
チャーリーホフマン

4

ラスターのリタイル専用のバンドルされた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


4

尋ねた@Aaronの場合:

拡張マルチコアおよびマルチスレッド操作のために-multiオプションを使用する@wwnickの答えのgdalwarpバージョンを見つけたい

わずかな免責事項

これはを使用しますがgdalwarp、パフォーマンスが大幅に向上すると確信しているわけではありません。これまでI / Oに縛られてきました-このスクリプトを大きなラスターで実行して多くの小さな部分に分割すると、CPUに負荷がかかりそうにないため、ボトルネックはディスクへの書き込みであると考えられます。タイルなどを同時に再投影することを計画している場合、これは変わる可能性があります。ここにチューニングのヒントがあります。短いプレイで改善されたわけではなく、CPUが制限要因になることはありませんでした。

免責事項は別としてgdalwarp、ラスターをいくつかの小さなタイルに分割するために使用するスクリプトを次に示します。フロア分割のためにいくらかの損失があるかもしれませんが、これはあなたが望むタイルの数を選ぶことによって世話をすることができます。それは次のようになりますn+1どこnあなたが取得することにより、分割数であるtile_widthtile_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))

3

GRASS GISのr.tileを使用できます。r.tileは、ユーザー定義のプレフィックスに基づいて番号付きのマップ名を使用して、タイルごとに個別のラスタマップを生成します。タイルの幅(列)とタイルの高さ(行)を定義できます。

Grass -Session Python API を使用すると、外部からr.tile機能を呼び出す、つまりスタンドアロンスクリプトを記述するのに必要なPythonコードは数行だけです。r.externalおよびr.external.outを使用しても、GRASS GIS処理ステップ中にデータの重複は発生しません。

擬似コード:

  1. 草セッションを初期化する
  2. r.external.outを使用して出力形式を定義する
  3. 入力ファイルをr.externalにリンクする
  4. 上記で定義された形式でタイルを生成するr.tileを実行します
  5. r.external.outのリンクを解除します
  6. グラスセッションを閉じる
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.