Membuat gambar dengan posisi lintang / bujur tertentu menggunakan GDAL?

9

Saya memiliki file ASCII dengan garis lintang, bujur, dan data_val dalam format berikut.

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

Saya memiliki file gambar GeoTiff, dan saya dapat dengan mudah melihatnya.

Saya ingin menempatkan "pin" (bisa berupa titik / bendera / bintang atau apa pun yang paling mudah) pada gambar di posisi lintang / bujur tertentu yang ditemukan dalam file ASCII.

Inilah yang telah saya lakukan sejauh ini:

Gambar sumber saya terlihat seperti ini:

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

Berikut adalah apa yang saya berhasil atur bersama di Python:

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

Tapi, saya tidak tahu bagaimana cara menempatkan "titik merah" di 35-13.643782N, 080-57.190157W

Saya harus mempelajari beberapa perincian baru di sini (nomenklatur tentang SIG).

Brad Walker
sumber
Topik yang mungkin perlu Anda selidiki adalah Georeferencing.
PolyGeo
Terima kasih .. Saya melakukan pencarian Google menggunakan istilah Georeferencing. Itu sangat membantu. Setengah pertempuran adalah mengetahui istilah teknis apa yang harus digunakan ..
Brad Walker
Saya yakin saya melewatkan sesuatu, tetapi apakah Anda sudah mempertimbangkan untuk mengubah data menjadi KML atau sesuatu?
barrycarter
1
Anda mungkin perlu mengubah koordinat DD-MM.mmmmH Anda menjadi derajat desimal. Anda harus menguraikan informasi Belahan S atau S berarti nilai negatif (lakukan itu sebagai langkah terakhir). Notulen perlu dibagi 60 dan ditambah atau digabungkan dengan porsi derajat.
mkennedy

Jawaban:

7

gdalinfoOutput Anda menunjukkan Anda memiliki satu band GeoTIFF dengan tabel warna (AKA palette). Saya tidak bisa melihat nilai-nilai dalam tabel warna itu sehingga perintah di bawah ini mengubah tabel warna + pita tunggal menjadi tiga pita RGB GeoTIFF. Perintah juga menganggap file ASCII Anda memiliki baris tajuk dan memiliki koordinat dalam derajat desimal, Anda mungkin perlu memodifikasi file Anda jika tidak.

Input:

$ 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

Proses:

$ 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

Perintah terakhir melakukan hal berikut:

  • buffer titik Lon / Lat ke poligon yang lebih besar sehingga terlihat lebih baik (Anda dapat melewatkannya jika Anda hanya ingin satu piksel berwarna merah)
  • mengkonversi dari WGS84 Lat / Lon (EPSG: 4326) ke sistem koordinat yang sama dengan raster (EPSG: 32754 yang merupakan WGS 84 UTM Zone 54S, CRS Anda akan berbeda)
  • menulis keluaran poligon sebagai GeoJSON ke STDOUT dan menyalurkannya ke gdal_rasterize
  • membakar RGB 255,0,0 ke dalam pita raster RGB 1, 2 & 3

Hasil:

masukkan deskripsi gambar di sini

pengguna2856
sumber
3

Anda memiliki awal yang baik. gdal.CreateCopyakan menangani georeferensi, sehingga Anda tidak perlu mengatur itu untuk kedua kalinya menggunakan geotransform dan proyeksi.

Proses yang lengkap akan mengubah lon / lat coords menjadi koordinat XY dari referensi spasial raster. Kemudian koordinat XY ini akan ditransformasikan menjadi baris, indeks col dari raster menggunakan geotransform terbalik. Beberapa nilai piksel akan ditulis pada posisi itu.

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

Catatan 1:

Perintah gdal.RasterBand.WriteArray(array, xoff, yoff)beroperasi dari sudut kiri atas. Dalam contoh ini saya menyediakan array 1x1 dengan nilai 255, jadi xoffdan yoffmerupakan baris aktual, indeks col untuk posisi lon / lat. Jika Anda ingin menulis kotak 3x3, Anda perlu menyesuaikan xoffdan yoffdengan mengurangi 1. Anda juga harus memastikan bahwa datatype array cocok dengan raster. Karena Anda mengatakan Anda ingin "titik merah", saya mengasumsikan ada tiga band uint8.

Logan Byers
sumber