GDAL kullanarak belirli enlem / boylam konumlarıyla görüntü oluşturuluyor mu?


9

Enlem, boylam ve data_val ile aşağıdaki biçimde bir ASCII dosyası var.

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

Bir GeoTiff görüntü dosyası var ve kolayca görüntüleyebiliyorum.

ASCII dosyasında bulunan belirli enlem / boylam konumunda bir "pim" (bir nokta / bayrak / yıldız veya en kolay olanı olabilir) yerleştirmek istiyorum.

Şimdiye kadar yapmayı başardım:

Kaynak resmim şöyle:

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

Python'da birlikte taş atmayı başardığım şey:

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

Ancak, 35-13.643782N, 080-57.190157W'de "kırmızı nokta" nasıl yerleştirileceğini tam olarak anlayamıyorum.

Burada bazı yeni detaylar öğrenmek zorundayım (CBS ile ilgili isimlendirme).


Araştırmanız gerekebilecek konu Georeferencing.
PolyGeo

Teşekkürler .. Georeferencing terimini kullanarak bazı Google aramaları yaptım. Bu yardımcı oldu. Savaşın yarısı hangi teknik terimlerin kullanılacağını biliyor ..
Brad Walker

Bir şey eksik olduğuma eminim, ancak verileri KML'ye veya başka bir şeye dönüştürmeyi düşündünüz mü?
barrycarter

1
DD-MM.mmmmH koordinatlarınızı ondalık dereceye dönüştürmeniz gerekebilir. Yarımküre bilgisini ayrıştırmanız gerekir W veya S negatif bir değer anlamına gelir (bunu son adım olarak yapın). Tutanağın 60'a bölünmesi ve derece bölümü ile birleştirilmesi veya birleştirilmesi gerekir.
mkennedy

Yanıtlar:


7

Sizin gdalinfoçıkış gösterir bir renk tablosu (AKA paleti) ile tek bir bant GeoTIFF var. Bu renk tablosundaki değerleri göremiyorum, böylece aşağıdaki komutlar tek bant + renk tablosunu üç bant RGB GeoTIFF'e dönüştürüyor. Komutlar ayrıca ASCII dosyanızın bir başlık satırı olduğunu ve ondalık derecelerde koordinatları olduğunu varsayarsa, dosyanızı değiştirmemeniz gerekebilir.

girişler:

$ 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

Süreci:

$ 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

Son komut aşağıdakileri yapar:

  • Lon / Lat noktasını daha büyük bir çokgene arabelleğe alır, böylece daha iyi görünür (sadece tek bir piksel kırmızı renkli istiyorsanız bunu atlayabilirsiniz)
  • WGS84 Lat / Lon'dan (EPSG: 4326) rasterle aynı koordinat sistemine dönüştürür (WGS 84 UTM Bölge 54S olan EPSG: 32754, CRS'niz farklı olacaktır)
  • çıkış çokgenini GeoJSON olarak STDOUT'a yazar ve gdal_rasterize
  • RGB 255,0,0'ı RGB tarama bantları 1, 2 ve 3'e yakar

Sonuç:

resim açıklamasını buraya girin


3

İyi bir başlangıç ​​yaptınız. gdal.CreateCopygeoreferencing ile ilgilenir, böylece geotransform ve projeksiyonu kullanarak ikinci kez ayarlamanız gerekmez.

Tüm süreç, lon / lat koordinatlarını raster uzamsal referansının XY koordinatlarına dönüştürecektir. Daha sonra bu XY koordinatları, ters jeotransform kullanılarak rasterdeki col indeksleri sıraya dönüştürülecektir. Bu konuma bir miktar piksel değeri yazılacaktır.

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

Not 1:

Komut gdal.RasterBand.WriteArray(array, xoff, yoff)sol üst köşeden çalışır. Bu örnekte 255 değerine sahip bir 1x1 dizisi sağlıyorum xoffve böylece yoffgerçek satır, lon / lat konumu için col indeksleri. 3x3 kare yazmak istiyorsanız, ayarlamanız xoffve yoff1 çıkarmanız gerekir. Ayrıca dizi veri türünün tarama ile eşleştiğinden de emin olmalısınız. "Kırmızı nokta" istediğinizi söylediğiniz için, üç uint8 grubu olduğunu varsayıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.