การสร้างภาพด้วยตำแหน่งละติจูด / ลองจิจูดเฉพาะโดยใช้ GDAL?


9

ฉันมีไฟล์ ASCII พร้อมละติจูด, ลองจิจูด, และ data_val ในรูปแบบต่อไปนี้

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

ฉันมีไฟล์ภาพ GeoTiff และฉันสามารถดูได้อย่างง่ายดาย

ฉันต้องการวาง "พิน" (อาจเป็นจุด / ธง / ดาวหรืออะไรก็ตามที่ง่ายที่สุด) ในภาพที่ตำแหน่งละติจูด / ลองจิจูดเฉพาะที่พบในไฟล์ ASCII

นี่คือสิ่งที่ฉันสามารถทำได้:

ภาพต้นฉบับของฉันดูเหมือนว่า:

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:

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

แต่ฉันไม่สามารถหาวิธีวาง "จุดสีแดง" ได้ที่ 35-13.643782N, 080-57.190157W

ฉันต้องเรียนรู้รายละเอียดใหม่ที่นี่ (ศัพท์เกี่ยวกับ GIS)


หัวข้อที่คุณอาจต้องตรวจสอบคือการอ้างอิงทางภูมิศาสตร์
PolyGeo

ขอบคุณ .. ฉันค้นหาด้วย Google โดยใช้คำว่า Georeferencing นั่นเป็นประโยชน์ ครึ่งหนึ่งของการต่อสู้คือรู้คำศัพท์ทางเทคนิคที่จะใช้ ..
Brad Walker

ฉันแน่ใจว่าฉันพลาดบางสิ่ง แต่คุณคิดว่าจะแปลงข้อมูลเป็น KML หรืออะไรบางอย่าง
barrycarter

1
คุณอาจต้องแปลงพิกัด DD-MM.mmmmH เป็นองศาทศนิยม คุณจะต้องแยกวิเคราะห์ข้อมูลซีกโลก W หรือ S หมายถึงค่าลบ (ทำตามขั้นตอนสุดท้าย) นาทีจะต้องหารด้วย 60 และเพิ่มหรือตัดแบ่งกับส่วนองศา
mkennedy

คำตอบ:


7

gdalinfoเอาท์พุทของคุณแสดงว่าคุณมีวงดนตรี GeoTIFF ที่มีตารางสี (จานสี AKA) ฉันไม่เห็นค่าในตารางสีดังกล่าวดังนั้นคำสั่งด้านล่างจะแปลงตารางเดียว + ตารางสีเป็น RGB GeoTIFF สามแถบ คำสั่งยังสมมติว่าไฟล์ ASCII ของคุณมีแถวส่วนหัวและมีพิกัดเป็นองศาทศนิยมคุณอาจต้องแก้ไขไฟล์หากไม่มี

ปัจจัยการผลิต:

$ 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

กระบวนการ:

$ 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

คำสั่งสุดท้ายทำสิ่งต่อไปนี้:

  • บัฟเฟอร์จุด Lon / Lat ไปที่รูปหลายเหลี่ยมที่ใหญ่กว่าเพื่อให้ปรากฏขึ้นได้ดีขึ้น (คุณสามารถข้ามไปได้หากคุณต้องการสีแดงพิกเซลเดียว)
  • แปลงจาก WGS84 Lat / Lon (EPSG: 4326) เป็นระบบพิกัดเดียวกับแรสเตอร์ (EPSG: 32754 ซึ่งเป็น WGS 84 UTM Zone 54S CRS ของคุณจะแตกต่างกัน)
  • เขียนรูปหลายเหลี่ยมเอาต์พุตเป็น GeoJSON ไปยัง STDOUT และไพพ์ไปที่ gdal_rasterize
  • เบิร์น RGB 255,0,0 ลงในแถบแรสเตอร์ RGB 1, 2 และ 3

ผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่


3

คุณมีจุดเริ่มต้นที่ดี gdal.CreateCopyจะดูแลการอ้างอิงทางภูมิศาสตร์ดังนั้นคุณไม่จำเป็นต้องตั้งค่าเป็นครั้งที่สองโดยใช้การเปลี่ยนรูปทางภูมิศาสตร์และการฉายภาพ

กระบวนการที่สมบูรณ์จะแปลง coon lon / lat เป็นพิกัด XY ของการอ้างอิงเชิงพื้นที่แรสเตอร์ จากนั้น coords XY เหล่านี้จะถูกเปลี่ยนเป็นแถว, ดัชนี col ของแรสเตอร์โดยใช้การแปลงทางภูมิศาสตร์แบบผกผัน ค่าพิกเซลบางค่าจะถูกเขียนที่ตำแหน่งนั้น

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

หมายเหตุ 1:

คำสั่งgdal.RasterBand.WriteArray(array, xoff, yoff)ดำเนินการจากมุมซ้ายบน ในตัวอย่างนี้ฉันได้จัดเตรียมอาร์เรย์ 1x1 ที่มีค่า 255 ดังนั้นxoffและyoffเป็นแถวจริงดัชนี col สำหรับตำแหน่ง lon / lat หากคุณต้องการเขียนสี่เหลี่ยม 3x3 คุณต้องปรับxoffและyoffลบ 1 คุณควรตรวจสอบให้แน่ใจว่าประเภทข้อมูลอาร์เรย์นั้นตรงกับของแรสเตอร์ เนื่องจากคุณบอกว่าคุณต้องการ "จุดสีแดง" ฉันถือว่ามีสามวง uint8

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.