Я перепроектую растри в python за допомогою GDAL. Мені потрібно спроектувати декілька тифів від географічних координат WGS 84 до Web Mercator WGS 1984 (допоміжна сфера), щоб згодом використовувати їх у Openlayers разом із OpenStreetMap та, можливо, картами Google. Я використовую Python 2.7.5 та GDAL 1.10.1 звідси і перетворюю координати, використовуючи поради звідси (мій код нижче). Словом, я імпортував osgeo.osr і використовував ImportFromEPSG (код) та CoordinateTransformation (від, до) .
Спершу я спробував EPSG (32629), який є UTM зоною 29, і отримав цей прогнозований растр (більш-менш тонкий), тому код здається правильним: Потім я використав EPSG (3857), тому що я прочитав це, і це питання і знайшов що це правильний недавній дійсний код . Але растр створюється взагалі без просторових орієнтирів. Це далеко в кадрі даних WGS 84 (але буде нормально, якщо я переключу фрейм даних на Web Mercator).
За допомогою EPSG (900913) вихід є геореференційним, але зміщеним приблизно на 3 растрові клітини на північ:
Коли я повторно відхиляю растр за допомогою ArcGIS (експорт у WGS_1984_Web_Mercator_Auxiliary_Sphere), результат майже чудовий:
І коли я використовую старий код 102113 (41001,54004), результат ідеальний:
Підсумок моїх тестів з використанням усіх кодів :
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
Тому мої запитання:
- Чому правильний код EPSG дає мені неправильні результати?
- І чому старі коди працюють нормально, вони не застаріли?
- Можливо, моя версія GDAL не є хорошою, або у мене є помилки в коді python?
Кодекс:
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'