使用GDAL用Python重新投影WGS 1984 Web Mercator(EPSG:3857)


17

我正在使用GDAL在python中重新投影栅格。我需要将多个tiff从地理WGS 84坐标投影到WGS 1984 Web Mercator(辅助领域),以便以后在Openlayers中与OpenStreetMap以及Google地图一起使用。我从这里开始使用Python 2.7.5和GDAL 1.10.1 ,并从这里开始使用建议转换坐标(我的代码在下面)。简而言之,我导入了osgeo.osr并使用了ImportFromEPSG (code)CoordinateTransformation(from,to)

我首先尝试EPSG(32629),这是UTM区29和得到这个投影光栅(或多或少罚款),所以代码似乎是正确的: utm 然后我用EPSG(3857) ,因为我读过这个这个问题,并发现这是正确的最近有效密码。但是创建的栅格完全没有空间参考。它在WGS 84数据帧中距离很远(但是如果我将数据帧切换到Web Mercator,就可以了)。 3857

使用EPSG(900913),输出已进行地理参考,但向北移动了约3个栅格像元: 900913

当我使用ArcGIS重新投影栅格时(在WGS_1984_Web_Mercator_Auxiliary_Sphere中导出),结果几乎是正确的: Arcgis

当我使用旧代码102113(41001,54004)时,结果是完美的: 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'

这可能会帮助我说些什么,我正在将栅格从EPSG:3042重新投影到Google Mercator栅格,我认为原则上是3857,但是当我尝试时:gdal_translate -a_srs EPSG:3857 input.tif output.tif,输出距离很远(GDAL 1.11.2),幸运的是,当使用ArcGIS 10.2和WGS_1984_Web_Mercator_Auxiliary_Sphere(WKID:3857授权:EPSG)对它们进行扭曲时,光栅图像位于正确的位置。因此,我相信在最新版本的GDAL中不能正确处理EPSG:3857。
Web-GIS企业家

3
重新投影后,栅格不再必须是矩形。因此,重新投影角坐标可能是错误的解决方案。您是否在命令行上尝试过gdalwarp?顺便说一句,您可以从gisinternals获得最新的GDAL版本。
AndreJ

Answers:


5

我会用重新投影文件gdalwarp

对于要转换为EPSG:3857的EPSG:3763中的文件,我执行了相同的操作。我使用QGIS和Geoserver比较了结果,生成的图像很好。由于对图像进行了很小的旋转,因此边框上可能会出现一些黑线(但是这些线之后可以变得透明)。

由于您有多个tif图像,因此可以使用像这样的脚本,该脚本不会更改任何现有文件,并将生成的文件放在名为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

如果您还想生成.twf文件,请添加listgeo

该脚本用于Linux,但是您可以为Windows编写类似的脚本。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.