Czy tworzysz obraz z określonymi pozycjami szerokości / długości geograficznej za pomocą GDAL?

9

Mam plik ASCII o szerokości i długości geograficznej oraz data_val w następującym formacie.

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

Mam plik obrazu GeoTiff i mogę go łatwo wyświetlić.

Chcę umieścić „pinezkę” (może być kropką / flagą / gwiazdą lub czymkolwiek najłatwiejszym) na obrazie na określonej szerokości / długości geograficznej znalezionej w pliku ASCII.

Oto, co udało mi się dotychczas zrobić:

Mój obraz źródłowy wygląda następująco:

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
...

Oto, co udało mi się połączyć w Pythonie:

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

Ale nie jestem w stanie dowiedzieć się, jak umieścić „czerwoną kropkę” na 35-13.643782N, 080-57.190157W

Muszę się tutaj nauczyć kilku nowych szczegółów (nomenklatura na temat GIS).

Brad Walker
źródło
Temat, który może być potrzebny do zbadania, to georeferencje.
PolyGeo
Dzięki .. Przeprowadziłem wyszukiwanie w Google przy użyciu terminu Georeferencing. To było pomocne. Połowa bitwy wie, jakich terminów technicznych użyć ...
Brad Walker,
Jestem pewien, że coś przeoczyłem, ale czy zastanawiałeś się nad konwersją danych do KML czy coś takiego?
barrycarter
1
Może być konieczne przekształcenie współrzędnych DD-MM.mmmmH na stopnie dziesiętne. Musisz przeanalizować informacje o półkuli W lub S oznacza wartość ujemną (zrób to jako ostatni krok). Minuty należy podzielić przez 60 i dodać lub połączyć z częścią stopni.
mkennedy

Odpowiedzi:

7

Twój gdalinfowynik pokazuje, że masz pojedynczy pasmo GeoTIFF z tabelą kolorów (paleta AKA). Nie widzę wartości w tej tabeli kolorów, więc poniższe polecenia konwertują tablicę jednopasmową i kolorową na trzypasmowy GeoTIFF RGB. Polecenia zakładają również, że plik ASCII ma wiersz nagłówka i współrzędne w stopniach dziesiętnych, w razie potrzeby może być konieczne zmodyfikowanie pliku.

Wejścia:

$ 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

Proces:

$ 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

Ostatnie polecenie wykonuje następujące czynności:

  • buforuje punkt Lon / Lat do większego wielokąta, aby wyświetlał się lepiej (możesz pominąć to, jeśli chcesz tylko jednego piksela w kolorze czerwonym)
  • konwertuje z WGS84 Lat / Lon (EPSG: 4326) na ten sam układ współrzędnych co raster (EPSG: 32754, który jest WGS 84 UTM Zone 54S, twój CRS będzie inny)
  • zapisuje wyjściowy wielokąt jako GeoJSON do STDOUT i potokuje go gdal_rasterize
  • wypala RGB 255,0,0 w pasmach rastrowych RGB 1, 2 i 3

Wynik:

wprowadź opis zdjęcia tutaj

użytkownik2856
źródło
3

Dobry początek. gdal.CreateCopyzajmie się georeferencją, więc nie musisz ustawiać tego ponownie za pomocą geotransformy i projekcji.

Cały proces przekształci współrzędne lon / lat w współrzędne XY odniesienia przestrzennego rastra. Następnie te współrzędne XY zostaną przekształcone w wiersz, indeksy col rastra za pomocą odwrotnej geotransformy. Pewna wartość w pikselach zostanie zapisana w tej pozycji.

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

Notatka 1:

Polecenie gdal.RasterBand.WriteArray(array, xoff, yoff)działa z lewego górnego rogu. W tym przykładzie podaję tablicę 1x1 o wartości 255, xoffa więc yoffsą to rzeczywiste indeksy wiersza, cola dla pozycji lon / lat. Jeśli chcesz napisać kwadrat 3x3, musisz dopasować xoffi yoffodejmując 1. Powinieneś także upewnić się, że typ danych tablicy pasuje do rastra. Ponieważ powiedziałeś, że chcesz „czerwonej kropki”, zakładam, że są trzy pasma uint8.

Logan Byers
źródło