Jak wywołać gdal_translate z kodu Python?

40

Czy można używać API gdal do wywoływania gdal_translatez kodu Python? Nie chodzi mi po prostu o uruchomienie gdal_translate.exe z systemu plików, ale raczej wywołanie go w kodzie, więc nie muszę znać dokładnego katalogu, w którym znajduje się plik wykonywalny gdal_translate?

Katie E.
źródło
4
Tak, od gdal-2.1. Ta odpowiedź powinna zostać zaakceptowana jako poprawna.
Pete,

Odpowiedzi:

27

Od GDAL 2.1 (więcej informacji tutaj ), narzędzia GDAL i OGR mogą być używane jako funkcje biblioteczne. Na przykład:

from osgeo import gdal

ds = gdal.Open('input.tif')
ds = gdal.Translate('output.tif', ds, projWin = [-75.3, 5.5, -73.5, 3.7])
ds = None
Antonio Falciano
źródło
2
Wszystkie dostępne opcje gdal.Translate()są wymienione tutaj: gdal.org/python/osgeo.gdal-module.html#TranslateOptions
Marcelo Villa
23

Zobacz samouczek interfejsu API GDAL .

#Import gdal
from osgeo import gdal

#Open existing dataset
src_ds = gdal.Open( src_filename )

#Open output format driver, see gdal_translate --formats for list
format = "GTiff"
driver = gdal.GetDriverByName( format )

#Output to new format
dst_ds = driver.CreateCopy( dst_filename, src_ds, 0 )

#Properly close the datasets to flush to disk
dst_ds = None
src_ds = None

Jeśli chcesz mieć większą kontrolę wyjściową, taką jak zmiana rozmiaru, podzbiór itp., Użyj VRT jako danych wejściowych, w ten sposób gdal_translate robi to wewnętrznie.

użytkownik2856
źródło
niestety nie obejmuje to powtórnego odrzucenia, prawda?
Riccardo
1
@ butcher - nie. Ponieważ w pytaniu nie wspomniano o ponownym odrzuceniu. Oczywiście możesz ponownie rzutować rastry za pomocą API gdal python. Jeśli chcesz wiedzieć, jak to zrobić, zadaj nowe pytanie.
user2856
Zrobiłem to już tutaj: gis.stackexchange.com/questions/103874/... ale ten został oznaczony jako duplikat :-(
Riccardo
2
@ Butcher - został zamknięty jako duplikat tego pytania. Twoje pytanie dotyczy także gdal_translate. Czy wiesz, że gdal_translate nie jest ponownie wyświetlany? Jeśli chcesz zmienić projekt, użyj metody API gdalwarp lub gdal python API - gdal.ReprojectImage
user2856
10

Tak, możesz wywołać narzędzia GDAL z poziomu Pythona. Istnieją bardzo niewielkie różnice w podejściu w zależności od tego, czy narzędzie to samo w sobie exe, czy też fragment kodu python. Tak czy inaczej, musisz użyć modułu podprocesu :

import subprocess

# constants
gdalTranslate = r'C:\Program Files\GDAL\gdal_translate.exe'
src = r"C:\somefolder\somefile.tif"
dst = r"C:\someotherfolder\myresul.tif"
cmd = "-ot float32 -outsize 25 25"  # just for example!

# see note below
def youCanQuoteMe(item):
    return "\"" + item + "\""

fullCmd = ' '.join([gdalTranslate, cmd, youCanQuoteMe(src), youCanQuoteMe(dst)])
subprocess.popen(fullCmd)

Zauważysz, że dodaję znaki cudzysłowu wokół moich ścieżek. Wynika to z faktu, że w systemie Windows miałem problemy ze ścieżkami, zwłaszcza ze spacjami lub gdy jedna z postaci „\” tworzy inną przypadkową postać, która uciekła. Więc po prostu zachowuję właściwą ścieżkę w Aspec.

Jeśli używasz jednego z narzędzi Pythona, po prostu zrób to samo, z tym że exe na początku łańcucha poleceń podprocesu ma teraz nazwę „C: \ python32 \ python.exe” (lub jakąkolwiek wersję masz), a drugim elementem jest narzędzie python, którego chcesz użyć.

Oczywiście możesz również iterować system plików zamiast używać stałych zakodowanych, ale to tylko przykład.

EDYCJA - Generalizacja dla wtyczek
QGIS QGIS tworzy / modyfikuje wiele zmiennych środowiskowych podczas uruchamiania. Możesz więc budować uogólnione zmienne ścieżki do bibliotek / narzędzi GDAL, używając tych (patrz Ustawienia-> Opcje-> System) zamiast ścieżek zakodowanych na stałe w powyższym przykładzie.

MappaGnosis
źródło
Więc nie mogę tego zrobić? zaimportować gdal_translate, a następnie wywołać .main ()?
Katie E.,
Nie - to nie zadziała. gdal_translate nie jest pakietem Pythona, więc python nic o nim nie wie. Pojawi się błąd „ImportError No Module o nazwie gdal_translate”. Zamiast tego użyj modułu podprocesu, aby go wywołać.
MappaGnosis
ok jedno podobne pytania przy użyciu gdal_retile.py .. Próbowałem wykonać następujące czynności: import gdal_retile gdal_retile.main ("- v -r bilinear -levels 4 -ps 2048 2048 -co \" tiled = YES \ "-targetDir cablepyramid - -optfile files.txt "), ale pojawia się błąd: Nierozpoznana opcja polecenia: - Wiesz, dlaczego?
Katie E.,
Z drugiej strony nie widzę problemu, z wyjątkiem mojego przypuszczenia, że ​​może nie podobać się przełącznik „--optfile”. Ten ostatni nie jest udokumentowany.
MappaGnosis
@MappaGnosis Czy istnieje alternatywa dla gdal_translate w bibliotece Python gdal?
multigoodverse
7

Robię to za pomocą różnych poleceń gdal za pomocą systemu os.system, którego można używać do wywoływania funkcji tak jak z wiersza poleceń:

os.system("gdal_translate -of GTiff " + sourcefile + " " +  destinationfile)

Jest to również opisane w wykładzie 7 tutaj: http://www.gis.usu.edu/~chrisg/python/2009/

Max
źródło
Komendy GDAL są dostępne jako funkcje Pythona w GDAL 2.1 do RFC 59.1 . subprocess.callJest także bezpieczniejszy niż os.system.
Dmitri Chubarov
1
Ktoś musi napisać dobry przykład tych funkcji Pythona; Zmagałem się z gdal.Warp()kilkoma godzinami, aby właściwie zdobyć PG:źródło danych, cutlineDSNameaby prowadzić cutlineSQL. (Wiem, prawda? Kilka godzin faktycznie coś wymyśliłem ? Horror! </kidding>). W końcu działa i wydaje się, że jest znacznie szybszy niż os.system()lub subprocess.call(). Robi ~ 2 miliony linii odcięcia, więc nie będę wiedział, czy to rzeczywiście szybciej do pewnego czasu dzisiejszej nocy ... ale działa dokładnie dobrze.
GT.
3

Oto szybki kod dla każdego, kto chce zapisać pasma z wielopasmowego kompozytu TIF do pojedynczych plików za pomocą GDAL Translate w Pythonie.

import gdal

in_path = 'C:/GIS/Sample.tif' #input composite raster
out_path = 'C:/GIS/Output/' #output directory for individual bands as files

#Open existing raster ds
src_ds = gdal.Open(in_path)

for i in range(1,src_ds.RasterCount +1): #Save bands as individual files
    out_ds = gdal.Translate(out_path + 'band' + str(i) + '.tiff', src_ds, format='GTiff', bandList=[i])
    out_ds=None

Może to być przydatne do dalszego przetwarzania (np. Przy użyciu Rasterio, jak tutaj ).

15 Krok
źródło