Raster GDAL kullanarak daha küçük parçalara bölünüyor mu?


18

Bir tarama (aslında USGS DEM) var ve aşağıdaki resimde gösterildiği gibi daha küçük parçalara bölmek gerekir. Bu, ArcGIS 10.0'da Split Raster aracı kullanılarak gerçekleştirildi. Bunu yapmak için bir FOSS yöntemi istiyorum. GDAL'a baktım, kesinlikle yapacağını düşünerek (bir şekilde gdal_translate ile), ama hiçbir şey bulamıyorum. Sonunda, raster almak ve ne kadar büyük (4KM parçaları tarafından 4KM) ayrılmak istiyorum söylemek istiyorum.

resim açıklamasını buraya girin


Birden fazla gdal çevirisini çalıştırmak için bir yardımcı programım var.Aynı zamanda, bir giriş kullanarak büyük bir raster çıkartmak için kullandığım, aynı zamanda, özellikle giriş ve / veya çıkış yüksek derecede sıkıştırılmışsa (örneğin, LZW veya deflate GeoTiff ), ikisi de yüksek oranda sıkıştırılmamışsa, işlem HDD erişiminde zirve yapar ve her seferinde bir tane çalıştırmaktan çok daha hızlı değildir. Ne yazık ki katı adlandırma kuralları nedeniyle paylaşmak için yeterince genel değil, yine de düşünce için yiyecek. GDALWarp için -multi seçeneği genellikle soruna neden olur ve yalnızca 2 iş parçacığı (bir okuma, bir yazma) kullanılamaz.
Michael Stimson

Yanıtlar:


18

gdal_translate , -srcwin veya -projwin seçeneklerini kullanarak çalışır.

-srcwin xoff yoff xsize ysize: Piksel / satır konumuna göre kopyalama için kaynak görüntüden bir alt pencere seçer.

-projwin ulx uly lrx lry: Kopyalamak için kaynak görüntüden (-srcwin gibi) ancak köşeleri coğrafi referanslı koordinatlarda verilen bir alt pencere seçer.

Piksel / çizgi konumları veya köşe koordinatları bulmanız ve ardından gdal_translate ile değerleri döngüye almanız gerekir. Piksel değerleri ve -srcwin kullanmak sizin için uygunsa, aşağıdaki hızlı ve kirli python gibi bir şey işe yarayacak, koordinatlarla sıralamak için biraz daha fazla çalışma olacaktır.

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
Merhaba bir geotiff görüntü ile -projwin seçeneği denediğimde uyarı alıyorum "Uyarı: Computed -srcwin -3005000 1879300 50 650 tamamen raster kapsamı dışında düşüyor. Ancak devam ediyorum" Yanlış yaptığımdan emin değilim coğrafi referanslı koordinatlarını kullanarak.
ncelik

@ncelik, büyük olasılıkla projwin'inizde hücre koordinatları kullandığınız ve bunun yerine srcwin kullanmanız gerektiğidir. Zorluk yaşıyorsanız, lütfen ilgili sorunlarınızla ilgili önerilerde bulunabilmemiz için ilgili tüm bilgileri içeren yeni bir soru gönderin .
Michael Stimson

15

@Wwnick'in temel aldığı çözümüm, raster boyutlarını dosyanın kendisinden okur ve gerekirse kenar döşemelerini küçülterek tüm görüntüyü kapsar:

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)

Bence sys.argv [1] sys.argv [2] yazıyor olmalı, değil mi?
oskarlin

3
sys.argv [2] çıktı dosyaları için önek olarak kullanıldığını düşünüyorum. Süper yararlı-- teşekkürler @Ries!
Charlie Hofmann

4

Özellikle radar_retile rasterleri yeniden dağıtmak için paketlenmiş bir python betiği vardır :

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

Örneğin:

gdal_retile.py -ps 512 512 -targetDir C:\example\dir some_dem.tif


4

Kim soran @Aaron için:

Geliştirilmiş çok çekirdekli ve çok iş parçacıklı işlemler için -multi seçeneğini kullanan @ wwnick yanıtının gdalwarp sürümünü bulmayı umuyorum

Hafif Feragat

Bu kullanır gdalwarp, ancak çok fazla performans kazancı olacağına ikna olmadım. Şimdiye kadar I / O bağlı oldum - bu komut dosyasını büyük bir taramada çalıştırmak, daha küçük parçalara kesmek CPU yoğun görünmüyor, bu yüzden darboğazın diske yazdığını varsayıyorum. Karoları veya benzer bir şeyi aynı anda yeniden yansıtmayı planlıyorsanız, bu değişebilir. Burada ayar ipuçları var . Kısa bir oyun benim için herhangi bir gelişme sağlamadı ve CPU hiçbir zaman sınırlayıcı bir faktör gibi görünmedi.

Feragatname bir yana, gdalwarpbir raster birkaç küçük karoya bölmek için kullanılacak bir komut dosyası . Zemin bölümü nedeniyle bir miktar kayıp olabilir, ancak bu istediğiniz karo sayısını seçerek halledilebilir. Ve değişkenlerini almak için böldüğünüz sayı n+1nerede olacaktır .ntile_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 kullanabilirsiniz . r.tile, kullanıcı tanımlı önek temelinde numaralandırılmış harita adlarına sahip her bir döşeme için ayrı bir raster haritası oluşturur. Döşemelerin genişliği (sütunlar) ve döşemelerin yüksekliği (satırlar) tanımlanabilir.

Grass-session Python API'sini kullanarak, r.tile işlevselliğini dışarıdan çağırmak, yani bağımsız bir komut dosyası yazmak için sadece birkaç satır Python kodu gerekir. R.external ve r.external.out kullanıldığında , GRASS GIS işleme adımı sırasında veri çoğaltma gerçekleşmez.

Sahte kod:

  1. çim oturumunu başlat
  2. r.external.out ile çıktı biçimini tanımlar
  3. giriş dosyasını r.external ile ilişkilendir
  4. karoları yukarıda tanımlanan formatta üreten r.tile dosyasını çalıştırın
  5. r.external.out bağlantısını kaldır
  6. kapanış oturumu
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.