GDALを使用したPythonでのWGS 1984 Webメルカトル(EPSG:3857)の再投影


17

GDALを使用してPythonでラスターを再投影しています。後でOpenStreetMapおよび多分Googleマップと一緒にOpenlayersで使用するために、地理的なWGS 84座標からWGS 1984 Webメルカトル(補助球)にいくつかのTIFFを投影する必要があります。私はここからPython 2.7.5とGDAL 1.10.1を使用し、ここからのアドバイスを使用して座標を変換しています(私のコードは下にあります)。つまり、osgeo.osrをインポートし、ImportFromEPSG(code)CoordinateTransformation(from、to)を使用しました

私は最初にUTMゾーン29であるEPSG(32629)を試し、この投影されたラスターを取得しました(多かれ少なかれ細かい)ので、コードは正しいようです: utm それから私はこれこの質問を読んで見つけたのでEPSG(3857)を使用しましたそれが正しい最近の有効なコードであること。ただし、ラスタは空間参照なしで作成されます。WGS 84データフレームでは遠く離れています(ただし、データフレームをWebメルカトルに切り替えても問題ありません)。 3857

EPSG(900913)出力が地理参照されているが、北に3つのラスタセルについてシフト: 900913

ArcGIS(WGS_1984_Web_Mercator_Auxiliary_Sphereにエクスポート)を使用してラスターを再投影すると、結果はほぼ問題ありません。 アークギス

そして、古いコード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メルカトルに再投影しています、私は原則として3857だと思っていましたが、試してみると:gdal_translate -a_srs EPSG:3857 input.tif output.tifの場合、幸いなことに、ArcGIS 10.2とWGS_1984_Web_Mercator_Auxiliary_Sphere(WKID:3857 Authority:EPSG)を使用してそれらをワープすると、ラスターイメージが適切な場所にあります(GDAL 1.11.2)。そのため、GDALの最新バージョンではEPSG:3857が適切に処理されないと考えています。
Web-GIS起業家

3
再投影後、ラスターはもはや長方形である必要はありません。したがって、コーナー座標を再投影することは間違った解決策かもしれません。コマンドラインでgdalwarpを試しましたか?ところで、最新のGDALバージョンはgisinternalsから入手できます。
-AndreJ

回答:


5

でファイルを再投影しますgdalwarp

EPSG:3763でEPSG:3857に変換したいファイルについても同じことをしました。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用にも似たようなものを書くことができます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.