Mit GDAL Bilder mit bestimmten Längen- und Breitengraden erstellen?

9

Ich habe eine ASCII-Datei mit Breiten-, Längen- und Datenwert im folgenden Format.

35-13.643782N, 080-57.190157W, 118.6
...

Ich habe eine GeoTiff-Bilddatei und kann sie problemlos anzeigen.

Ich möchte einen "Stift" (kann ein Punkt / eine Flagge / ein Stern oder was auch immer am einfachsten ist) auf dem Bild an der spezifischen Breiten- / Längengradposition platzieren, die in der ASCII-Datei gefunden wird.

Folgendes habe ich bisher geschafft:

Mein Quellbild sieht folgendermaßen aus:

Driver: GTiff/GeoTIFF
Files: /tmp/Charlotte SEC 100.tif
Size is 16867, 12358
Coordinate System is:
PROJCS["Lambert Conformal Conic",
    GEOGCS["NAD83",
        DATUM["North_American_Datum_1983",
            SPHEROID["GRS 1980",6378137,298.2572221010042,
                AUTHORITY["EPSG","7019"]],
            AUTHORITY["EPSG","6269"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4269"]],
    PROJECTION["Lambert_Conformal_Conic_2SP"],
    PARAMETER["standard_parallel_1",38.66666666666666],
    PARAMETER["standard_parallel_2",33.33333333333334],
    PARAMETER["latitude_of_origin",34.11666666666667],
    PARAMETER["central_meridian",-78.75],
    PARAMETER["false_easting",0],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]]]
Origin = (-365041.822331817995291,240536.419747152860509)
Pixel Size = (42.334586069440391,-42.334898968590878)
Metadata:
  AREA_OR_POINT=Area
  TIFFTAG_DATETIME=2016:06:24 12:46:45
  TIFFTAG_RESOLUTIONUNIT=2 (pixels/inch)
  TIFFTAG_SOFTWARE=Adobe Photoshop CS5 Windows
  TIFFTAG_XRESOLUTION=300
  TIFFTAG_YRESOLUTION=300
Image Structure Metadata:
  COMPRESSION=LZW
  INTERLEAVE=BAND
Corner Coordinates:
Upper Left  ( -365041.822,  240536.420) ( 82d48'55.43"W, 36d13' 4.92"N)
Lower Left  ( -365041.822, -282638.262) ( 82d35'10.11"W, 31d30'17.00"N)
Upper Right (  349015.641,  240536.420) ( 74d51'46.40"W, 36d13'26.16"N)
Lower Right (  349015.641, -282638.262) ( 75d 4'55.60"W, 31d30'36.99"N)
Center      (   -8013.091,  -21050.921) ( 78d50'12.11"W, 33d55'36.35"N)
Band 1 Block=16867x1 Type=Byte, ColorInterp=Palette
  Color Table (RGB with 256 entries)
    0: 255,255,255,255
...

Folgendes habe ich in Python zusammengeschustert:

from osgeo import gdal, osr

src_filename = '/tmp/Charlotte SEC 100.tif'
dst_filename = '/tmp/foo.tiff'

# Opens source dataset
src_ds = gdal.Open(src_filename)
format = "GTiff"
driver = gdal.GetDriverByName(format)

# Open destination dataset
dst_ds = driver.CreateCopy(dst_filename, src_ds, 0)

# Specify raster location through geotransform array
# (upperleftx, scalex, skewx, upperlefty, skewy, scaley)
# Scale = size of one pixel in units of raster projection
# this example below assumes 100x100
gt = [-365041.822, 100, 0, 240536.420, 0, -100]

# Set location
dst_ds.SetGeoTransform(gt)

# Get raster projection
epsg = 4269            # http://spatialreference.org/ref/sr-org/lambert_conformal_conic_2sp/
srs = osr.SpatialReference()
srs.ImportFromEPSG(epsg)
dest_wkt = srs.ExportToWkt()

# Set projection
dst_ds.SetProjection(dest_wkt)

# Close files
dst_ds = None
src_ds = None

Aber ich kann nicht genau herausfinden, wie man einen "roten Punkt" bei 35-13.643782N, 080-57.190157W platziert

Ich muss hier einige neue Details lernen (Nomenklatur über GIS).

Brad Walker
quelle
Das Thema, das Sie möglicherweise untersuchen müssen, ist Georeferenzierung.
PolyGeo
Vielen Dank. Ich habe eine Google-Suche mit dem Begriff Georeferenzierung durchgeführt. Das war hilfreich. Die halbe Miete ist zu wissen, welche technischen Begriffe zu verwenden sind.
Brad Walker
Ich bin mir sicher, dass mir etwas fehlt, aber haben Sie darüber nachgedacht, die Daten in KML zu konvertieren oder so?
Barrycarter
1
Möglicherweise müssen Sie Ihre DD-MM.mmmmH-Koordinaten in Dezimalgrade konvertieren. Sie müssen die Hemisphäre-Informationen analysieren. W oder S bedeutet einen negativen Wert (tun Sie dies als letzten Schritt). Die Minuten müssen durch 60 geteilt und mit dem Gradanteil addiert oder verkettet werden.
Mkennedy

Antworten:

7

Ihre gdalinfoAusgabe zeigt, dass Sie ein Einzelband-GeoTIFF mit einer Farbtabelle (AKA-Palette) haben. Ich kann die Werte in dieser Farbtabelle nicht sehen, daher konvertieren die folgenden Befehle die Einzelband- + Farbtabelle in ein Drei-Band-RGB-GeoTIFF. Die Befehle setzen auch voraus, dass Ihre ASCII-Datei eine Kopfzeile und Koordinaten in Dezimalgraden hat. Möglicherweise müssen Sie Ihre Datei ändern, wenn dies nicht der Fall ist.

Eingaben:

$ cat testlonlat.csv
LON,LAT
143.798425,-15.551485
143.827437,-15.535119
143.84561,-15.530017
143.859107,-15.54819
143.812347,-15.523641
143.853581,-15.534694
143.883337,-15.537669
143.885356,-15.561687
143.887694,-15.588468

$ gdalinfo testutm.tif
Driver: GTiff/GeoTIFF
Files: testutm.tif
Size is 1102, 959
Coordinate System is:
PROJCS["WGS 84 / UTM zone 54S",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",141],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",10000000],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["Easting",EAST],
    AXIS["Northing",NORTH],
    AUTHORITY["EPSG","32754"]]
Origin = (798741.168775000027381,8282084.855279999785125)
Pixel Size = (10.000000000000000,-10.000000000000000)
Metadata:
  AREA_OR_POINT=Area
Image Structure Metadata:
  INTERLEAVE=BAND
Corner Coordinates:
Upper Left  (  798741.169, 8282084.855) (143d47' 4.96"E, 15d31'16.22"S)
Lower Left  (  798741.169, 8272494.855) (143d47' 9.15"E, 15d36'27.98"S)
Upper Right (  809761.169, 8282084.855) (143d53'14.43"E, 15d31'11.47"S)
Lower Right (  809761.169, 8272494.855) (143d53'18.78"E, 15d36'23.20"S)
Center      (  804251.169, 8277289.855) (143d50'11.83"E, 15d33'49.74"S)
Band 1 Block=1102x7 Type=Byte, ColorInterp=Palette
  Color Table (RGB with 256 entries)
    0: 120,112,136,255
    1: 96,104,88,255
    ...
    254: 76,124,140,255
    255: 232,228,236,255

Prozess:

$ gdal_translate -expand rgb testutm.tif testutm_rgb.tif

$ ogr2ogr -f "GeoJSON" -dialect sqlite                      \
  -sql "select ST_buffer(Geometry,0.001) from testlonlat"   \
  -s_srs EPSG:4326 -t_srs EPSG:32754                        \
  /vsistdout/ CSV:testlonlat.csv -oo X_POSSIBLE_NAMES=Lon   \
  -oo Y_POSSIBLE_NAMES=Lat |  gdal_rasterize -b 1 -b 2 -b 3 \
  -burn 255 -burn 0 -burn 0 /vsistdin/ testutm_rgb.tif

Der letzte Befehl führt Folgendes aus:

  • Puffert den Lon / Lat-Punkt auf ein größeres Polygon, damit es besser angezeigt wird (Sie können dies überspringen, wenn Sie nur ein einzelnes rot gefärbtes Pixel möchten).
  • Konvertiert von WGS84 Lat / Lon (EPSG: 4326) in dasselbe Koordinatensystem wie das Raster (EPSG: 32754, WGS 84 UTM Zone 54S, Ihr CRS ist unterschiedlich).
  • schreibt das Ausgabepolygon als GeoJSON in STDOUT und leitet es an weiter gdal_rasterize
  • Brennt RGB 255,0,0 in die RGB-Rasterbänder 1, 2 und 3

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

user2856
quelle
3

Du hast einen guten Start. gdal.CreateCopykümmert sich um die Georeferenzierung, so dass Sie dies nicht ein zweites Mal mithilfe der Geotransform und der Projektion einstellen müssen.

Der gesamte Prozess transformiert die Lon / Lat-Koordinaten in die XY-Koordinaten des Raster-Raumbezugs. Dann werden diese XY-Koordinaten unter Verwendung der inversen Geotransform in die Zeilen- und Spaltenindizes des Rasters umgewandelt. An dieser Position wird ein Pixelwert geschrieben.

from osgeo import gdal, osr
import numpy as np

src_filename = '/tmp/Charlotte SEC 100.tif'
dst_filename = '/tmp/foo.tiff'

# Opens source dataset
src_ds = gdal.Open(src_filename)
format = "GTiff"
driver = gdal.GetDriverByName(format)

# Open destination dataset
dst_ds = driver.CreateCopy(dst_filename, src_ds, 0)

# Get raster projection
epsg = 4269         # http://spatialreference.org/ref/sr-org/lambert_conformal_conic_2sp/
srs = osr.SpatialReference()
srs.ImportFromEPSG(epsg)

# Make WGS84 lon lat coordinate system
world_sr = osr.SpatialReference()
world_sr.SetWellKnownGeogCS('WGS84')

# Transform lon lats into XY
lonlat = [[0.,30.], [20., 30.], [25., 30.]]
coord_transform = osr.CoordinateTransformation(world_sr, srs)
newpoints = coord_transform.TransformPoints(lonlat) # list of XYZ tuples

# Make Inverse Geotransform  (try:except due to gdal version differences)
try:
    success, inverse_gt = gdal.InvGeoTransform(gt)
except:
    inverse_gt = gdal.InvGeoTransform(gt)

# [Note 1] Set pixel values
marker_array_r = np.array([[255]], dtype=np.uint8)
marker_array_g = np.array([[0]], dtype=np.uint8)
marker_array_b = np.array([[0]], dtype=np.uint8)
for x,y,z in newpoints:
    pix_x = int(inverse_gt[0] + inverse_gt[1] * x + inverse_gt[2] * y)
    pix_y = int(inverse_gt[3] + inverse_gt[4] * x + inverse_gt[5] * y)
    dst_ds.GetRasterBand(1).WriteArray(marker_array_r, pix_x, pix_y)
    dst_ds.GetRasterBand(2).WriteArray(marker_array_g, pix_x, pix_y)
    dst_ds.GetRasterBand(3).WriteArray(marker_array_b, pix_x, pix_y)

# Close files
dst_ds = None
src_ds = None

Anmerkung 1:

Der Befehl wird gdal.RasterBand.WriteArray(array, xoff, yoff)in der oberen linken Ecke ausgeführt. In diesem Beispiel liefern I ein 1x1 - Array mit dem Wert 255, so , xoffund yoffsind die tatsächlichen Zeile, Spalte Indizes für die lon / lat Position. Wenn Sie ein 3x3-Quadrat schreiben möchten, müssen Sie es anpassen xoffund yoffdurch Subtrahieren von 1. Sie sollten auch sicherstellen, dass der Array-Datentyp mit dem des Rasters übereinstimmt. Da Sie sagten, Sie möchten einen "roten Punkt", gehe ich davon aus, dass es drei Bänder von uint8 gibt.

Logan Byers
quelle