เอาท์พุทอาเรย์ข้อมูลแบบแรสเตอร์พลิกบนแกน x โดยใช้ python / gdal?


9

ฉันกำลังพยายามสร้างแรสเตอร์โดยใช้ไลบรารี python gdal และฉันได้ไปยังจุดที่ข้อมูลกำลังถูกส่งออก แต่ข้อมูลเอาต์พุตถูกพลิกบนแกน x ของจุดกำเนิด ฉันรู้ว่าฉันต้องมองข้ามบางสิ่งบางอย่าง แต่ฉันไม่สามารถเข้าใจได้ว่าฉันกำลังทำอะไรอยู่ ความคิดใด ๆ

เมื่อสร้างแรสเตอร์ฉันจะตั้งค่า x / y บนซ้ายและอาเรย์ดูเหมือนจะได้รับการจัดทำดัชนีจากบนซ้ายและดำเนินการต่อไปจนถึงล่างขวา ในรหัสด้านล่างฉันเติมอาร์เรย์ด้วยค่าของแถว

เมื่อพิมพ์อาเรย์ออกมามันจะเป็นดังนี้:

[[  1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.
    1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.
    1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.   1.
    1.   1.   1.   1.   1.   1.]
 [  2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.
    2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.
    2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.   2.
    2.   2.   2.   2.   2.   2.]
 [  3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.
    3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.
    3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.   3.
    3.   3.   3.   3.   3.   3.]
 [  4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.
    4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.
    4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.   4.
    4.   4.   4.   4.   4.   4.]
...

และข้อมูลนี้เขียนลงในแถบแรสเตอร์ได้สำเร็จ อย่างไรก็ตามเมื่อดูในMapWindow GISข้อมูลจะปรากฏไปในทิศทางตรงกันข้ามโดยมีจุดกำเนิดบนซ้ายตั้ง แต่แรกปรากฏเป็นค่าซ้ายล่าง

กล่าวอีกนัยหนึ่งคือข้อมูลถูกพลิกบนแกน x ของจุดกำเนิด

import gdal
import osr
import numpy

OUTPUT_FORMAT = "GTiff"
def create_raster(filename="test.tif"):
    driver = gdal.GetDriverByName(OUTPUT_FORMAT)
    band_type = gdal.GDT_Byte
    number_of_bands = 1

    x_rotation = 0 # not supported
    y_rotation = 0 # not supported
    cell_width_meters = 50
    cell_height_meters = 50

    (min_lon, min_lat, max_lon, max_lat) = _get_point_bounds() # retrieve bounds for point data        
    srs = osr.SpatialReference()
    srs.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon        
    srs.SetUTM( 54, True) # Set projected coordinate system  to handle meters        

    # create transforms for point conversion
    wgs84_coordinate_system = srs.CloneGeogCS() # clone only the geographic coordinate system
    wgs84_to_utm_transform = osr.CoordinateTransformation(wgs84_coordinate_system, srs)

    # convert to UTM
    top_left_x, top_left_y, z = wgs84_to_utm_transform.TransformPoint(min_lon, max_lat, 0)     
    lower_right_x, lower_right_y, z = wgs84_to_utm_transform.TransformPoint(max_lon, min_lat, 0) 

    cols, rows = _get_raster_size(top_left_x, lower_right_y, lower_right_x, top_left_y, cell_width_meters, cell_height_meters)
    dataset = driver.Create(filename, cols, rows, number_of_bands, band_type) #

    # GeoTransform parameters
    # --> need to know the area that will be covered to define the geo tranform
    # top left x, w-e pixel resolution, rotation, top left y, rotation, n-s pixel resolution
    geo_transform = [ top_left_x, cell_width_meters, x_rotation, top_left_y, y_rotation, cell_height_meters ]
    dataset.SetGeoTransform(geo_transform)
    dataset.SetProjection(srs.ExportToWkt())

    dataset_band = dataset.GetRasterBand(1)
    data = dataset_band.ReadAsArray(0, 0, cols, rows).astype(numpy.float32) # returns empty array 

    for row in xrange(rows):
        for col in xrange(cols):
            data[row][ col] = row + 1

    dataset_band.WriteArray(data, 0, 0)
    dataset_band.SetNoDataValue(0.0)
    dataset_band.FlushCache()
    dataset = None # Close file

ฉันได้สังเกตเห็นเมื่อฉันคำนวณตำแหน่งพิกเซลสำหรับการรับ lat lon / ค่า yผลลัพธ์ในดัชนีเชิงลบซึ่งดูเหมือนว่าการจัดเรียงของที่ถูกต้องพิจารณาว่าอาร์เรย์จากบนซ้ายไปขวาล่าง

inverse_geo_transform = gdal.InvGeoTransform(self.geo_transform)[1] # for mapping lat/lon to pixel
pixel_x, pixel_y = gdal.ApplyGeoTransform(self.inverse_geo_transform, utm_x, utm_y)

คำตอบ:


10

ฉันพบปัญหา ....

ปัญหาเกิดขึ้นในการกำหนด geo_transform ฉันมีดังต่อไปนี้:

x_rotation = 0 
y_rotation = 0 
cell_width_meters = 50
cell_height_meters = 50

geo_transform = [ top_left_x, cell_width_meters, x_rotation, top_left_y, y_rotation, cell_height_meters ]
dataset.SetGeoTransform(geo_transform)

เอกสาร Gdal ไม่ชัดเจนเกี่ยวกับค่าเหล่านี้ (ดูSetGeoTransform ) ค้นหารอบ internets ฉันได้รับว่าค่าที่ผ่านควรเป็น (ตามลำดับ):

  • top_left_x
  • cell_width_meters
  • x_rotation
  • top_left_y
  • y_rotation
  • cell_height_meters

สิ่งใดที่ดูเหมือนว่าถูกต้องแต่ทบทวนบทช่วยสอน GDAL APIอีกครั้งฉันสังเกตเห็นว่ามีการแสดงค่าสุดท้ายที่cell_height_metersได้รับเป็นค่าลบ ดูเหมือนว่านี่คือทั้งหมดที่จำเป็นในการส่งออกข้อมูลอย่างถูกต้องในทิศทางที่คาดหวัง

ดังนั้นตอนนี้ฉันได้เปลี่ยนบรรทัดคำจำกัดความของgeo_transformเป็น:

(สังเกตการเพิ่ม "-")

geo_transform = [ top_left_x, cell_width_meters, x_rotation, top_left_y, y_rotation, -cell_height_meters ]

นี่เป็นวิธีการดั้งเดิมในการจัดการกับโลกภาพเหมือนต้นกำเนิดที่มุมซ้ายบนและวิธีการใช้ภูมิศาสตร์ของซ้ายล่าง
Ian Turton

มันสมเหตุสมผลเมื่อคุณรู้ แต่ใกล้ถึงปัญหาจากตัวอย่างโค้ดมันยากที่จะรับเหตุผล ฉันพบว่าเอกสาร ArcGIS มีเอกสารที่ยอดเยี่ยมที่อธิบายเกี่ยวกับ rasters: webhelp.esri.com/arcgisdesktop/9.3/…
monkut
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.