GDAL을 사용하여 래스터를 작은 덩어리로 나누시겠습니까?


18

나는 래스터 (USGS DEM)를 가지고 있으며 아래 그림과 같이 작은 덩어리로 나눠야합니다. 이는 Split Raster 도구를 사용하여 ArcGIS 10.0에서 수행되었습니다. 이를 위해 FOSS 방법을 원합니다. GDAL을 살펴 보았지만 (gdal_translate를 사용하여) 확실히 할 것이라고 생각했지만 아무것도 찾을 수 없었습니다. 궁극적으로 래스터를 가져 와서 얼마나 큰지 (4KM x 4KM 청크)로 나누고 싶습니다.

여기에 이미지 설명을 입력하십시오


subprocess를 사용하는 유틸리티가 있습니다 .Popen은 여러 개의 gdal 번역을 동시에 실행하여 fishnet을 사용하여 타일에 큰 래스터를 추출하는 데 사용합니다. 특히 입력 및 / 또는 출력이 고도로 압축 된 경우에 유용합니다 (예 : LZW 또는 Deflate GeoTiff) ), 둘 다 압축되지 않은 경우 프로세스는 HDD 액세스에서 최고이며 한 번에 하나씩 실행하는 것보다 훨씬 빠르지 않습니다. 불행히도 명명 규칙이 엄격하기 때문에 공유하기에는 일반적이지 않지만 어쨌든 생각할 음식입니다. GDALWarp의 -multi 옵션은 종종 문제를 일으켜 2 개의 스레드 (하나의 읽기, 하나의 쓰기) 만 사용할 수 있습니다.
Michael Stimson

답변:


18

gdal_translate 는 -srcwin 또는 -projwin 옵션을 사용하여 작동합니다.

-srcwin xoff yoff xsize ysize : 소스 이미지에서 픽셀 / 라인 위치를 기준으로 복사 할 하위 창을 선택합니다.

-projwin ulx uly lrx lry : 복사 할 소스 이미지에서 -srcwin과 같은 서브 윈도우를 선택하지만 모서리는 지리 참조 좌표로 제공됩니다.

픽셀 / 라인 위치 또는 코너 좌표를 찾은 다음 gdal_translate를 사용하여 값을 반복해야합니다. 픽셀 값을 사용하고 -srcwin이 적합한 경우 아래의 빠르고 더러운 파이썬과 같은 것이 작동합니다. 좌표로 정렬하는 것이 조금 더 많은 작업입니다.

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
안녕하세요. geotiff 이미지로 -projwin 옵션을 시도하면 "경고 : Computed -srcwin -3005000 1879300 50 650이 래스터 범위를 완전히 벗어났습니다. 그러나 계속 진행합니다"라는 경고 메시지가 나타납니다. 지리 참조 좌표 사용
ncelik

@ncelik 아마도 projwin에서 셀 좌표를 사용하고 srcwin을 대신 사용해야하기 때문일 수 있습니다. 문제가 발생하면 모든 관련 정보 와 함께 새로운 질문을 게시 하여 특정 문제에 대한 제안을 할 수 있습니다.
Michael Stimson

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]이어야한다고 생각합니까?
oskarlin

3
sys.argv [2]는 출력 파일의 접두사로 사용됩니다. 매우 도움이되었습니다. @Ries에게 감사합니다!
Charlie Hofmann

4

래스터를 줄이기 위해 번들로 제공되는 번들 파이썬 스크립트 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+1n얻가 당신에 의해 분할 개수 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은 사용자 정의 접두사를 기반으로 번호가 매겨진 맵 이름을 가진 각 타일에 대해 별도의 래스터 맵을 생성합니다. 타일 ​​너비 (열) 및 타일 높이 (행)를 정의 할 수 있습니다.

풀 세션 Python API를 사용하면 외부에서 r.tile 기능을 호출하는 데 (예 : 독립형 스크립트 작성) 몇 줄의 Python 코드 만 필요합니다. r.externalr.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.