Riproiezione di WGS 1984 Web Mercator (EPSG: 3857) in Python con GDAL


17

Sto riproiettando raster in Python usando GDAL. Devo proiettare diverse tiff dalle coordinate geografiche WGS 84 a WGS 1984 Web Mercator (sfera ausiliaria), per poterle utilizzare in seguito in Openlayers insieme a OpenStreetMap e forse a Google Maps. Sto usando Python 2.7.5 e GDAL 1.10.1 da qui , e trasformando le coordinate usando i consigli da qui (il mio codice è sotto). In breve, ho importato osgeo.osr e ho usato ImportFromEPSG (code) e CoordinateTransformation (da, a) .

Ho provato prima EPSG (32629) che è UTM zona 29 e ho ottenuto questo raster proiettato (più o meno bene), quindi il codice sembra essere corretto: utm Poi ho usato EPSG (3857) perché ho letto questo e questo domande e ho trovato che è il codice valido recente recente corretto . Ma il raster viene creato senza alcun riferimento spaziale. È molto lontano nel frame di dati WGS 84 (ma andrà bene se cambio il frame di dati in Web Mercator). 3857

Con EPSG (900913) l'output è georeferenziato, ma spostato di circa 3 celle raster a nord: 900913

Quando riproiettare il raster utilizzando ArcGIS (esportazione in WGS_1984_Web_Mercator_Auxitime_Sphere) il risultato è quasi perfetto: ArcGIS

E quando uso il vecchio codice 102113 (41001,54004) il risultato è perfetto: 54004

Il riassunto dei miei test usando tutti i codici :

3857: far away up (missing georeference)
3785: far away up (like 3857)
3587: far away right
900913: slightly jumped up
102100: python error
102113: perfect
41001: perfect
54004: perfect
ArcGIS (web merc. aux.): good

Quindi le mie domande sono:

  • Perché il codice EPSG corretto mi dà risultati errati?
  • E perché i vecchi codici funzionano bene, non sono deprecati?
  • Forse la mia versione GDAL non è buona o ho errori nel mio codice Python?

Il codice:

    yres = round(lons[1]-lons[0], 4)  # pixel size, degrees
    xres = round(lats[1]-lats[0], 4)
    ysize = len(lats)-1  # number of pixels
    xsize = len(lons)-1
    ulx = round(lons[0], 4)
    uly = round(lats[-1], 4)  # last
    driver = gdal.GetDriverByName(fileformat)
    ds = driver.Create(filename, xsize, ysize, 2, gdal.GDT_Float32)  # 2 bands
    #--- Geographic ---
    srs = osr.SpatialReference()
    srs.ImportFromEPSG(4326)  # Geographic lat/lon WGS 84
    ds.SetProjection(srs.ExportToWkt())
    gt = [ulx, xres, 0, uly, 0, -yres]  # the affine transformation coeffs (ulx, pixel, angle(skew), uly, angle, -pixel)
    ds.SetGeoTransform(gt)  # coords of top left corner of top left pixel (w-file - center of the pixel!)
    outband = ds.GetRasterBand(1)
    outband.WriteArray(data)
    outband2 = ds.GetRasterBand(2)
    outband2.WriteArray(data3)
    #--- REPROJECTION ---
    utm29 = osr.SpatialReference()
#    utm29.ImportFromEPSG(32629)  # utm 29
    utm29.ImportFromEPSG(900913)  # web mercator 3857
    wgs84 = osr.SpatialReference()
    wgs84.ImportFromEPSG(4326)
    tx = osr.CoordinateTransformation(wgs84,utm29)
    # Get the Geotransform vector
    # Work out the boundaries of the new dataset in the target projection
    (ulx29, uly29, ulz29) = tx.TransformPoint(ulx, uly)  # corner coords in utm meters
    (lrx29, lry29, lrz29) = tx.TransformPoint(ulx + xres*xsize, uly - yres*ysize )
    filenameutm = filename[0:-4] + '_web.tif'
    dest = driver.Create(filenameutm, xsize, ysize, 2, gdal.GDT_Float32)
    xres29 = round((lrx29 - ulx29)/xsize, 2) # pixel size, utm meters
    yres29 = abs(round((lry29 - uly29)/ysize, 2))
    new_gt = [ulx29, xres29, 0, uly29, 0, -yres29]
    dest.SetGeoTransform(new_gt)
    dest.SetProjection(utm29.ExportToWkt())
    gdal.ReprojectImage(ds, dest, wgs84.ExportToWkt(), utm29.ExportToWkt(), gdal.GRA_Bilinear)
    dest.GetRasterBand(1).SetNoDataValue(0.0)
    dest.GetRasterBand(2).SetNoDataValue(0.0)
    dest = None  # Flush the dataset to the disk
    ds = None  # only after the reprojected!
    print 'Image Created'

Potrebbe essere d'aiuto quello che sto per dire, sto riproiettando un raster dall'EPSG: 3042 a quello di Google Mercator, ho pensato di essere il 3857, ma quando provo: gdal_translate -a_srs EPSG: 3857 input.tif output.tif, l'output è molto più in basso (GDAL 1.11.2), per fortuna quando li deformi usando ArcGIS 10.2 e WGS_1984_Web_Mercator_Auxitime_Sphere (WKID: 3857 Authority: EPSG) le immagini raster sono nel posto giusto. Quindi, credo che EPSG: 3857 non sia gestito correttamente nelle ultime versioni di GDAL.
Imprenditore Web-GIS il

3
Dopo la riproiezione, il raster non deve più essere un rettangolo. Quindi riproiettare le coordinate degli angoli potrebbe essere la soluzione sbagliata. Hai provato gdalwarp dalla riga di comando? A proposito, puoi ottenere l'ultima versione GDAL da gisinternals.
AndreJ,

Risposte:


5

Riproietterei i file con gdalwarp.

Ho fatto lo stesso per i file in EPSG: 3763 che voglio convertire in EPSG: 3857. Ho confrontato i risultati usando QGIS e Geoserver e le immagini generate andavano bene. Poiché viene applicata una piccola rotazione alle immagini, è possibile che sul bordo vengano visualizzate alcune linee nere (ma queste linee possono essere rese trasparenti in seguito).

Dato che hai diverse tifimmagini, puoi usare uno script come questo che non modifica alcun file esistente e mette i file generati in una cartella chiamata 3857:

#!/bin/bash
mkdir 3857
for file in $(ls *.tif); do
    gdalwarp -s_srs EPSG:3763 -t_srs EPSG:3857 $file 3857/$file;
    listgeo -tfw 3857/$file;
done

Se vuoi anche generare i .twffile, ho aggiunto listgeo.

Questo script è per Linux, ma puoi scrivere qualcosa di simile per Windows.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.