Đầu ra mảng dữ liệu raster được lật trên trục x bằng python / gdal?


9

Tôi đang cố gắng tạo một raster bằng các thư viện gdal python và tôi đã đến điểm mà dữ liệu đang được xuất ra, nhưng dữ liệu đầu ra được lật trên trục x của điểm gốc . Tôi biết tôi phải xem xét một cái gì đó, nhưng tôi không thể tìm ra mình đang sai ở đâu. Có ý kiến ​​gì không?

Khi tạo raster tôi đặt các giá trị x / y phía trên bên trái và mảng dường như được lập chỉ mục từ phía trên bên trái và tiếp tục xuống phía dưới bên phải. Trong đoạn mã dưới đây, tôi sẽ điền vào mảng với giá trị của hàng.

Khi in mảng ra, nó trông như thế nà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.]
...

Và dữ liệu này ghi thành công vào ban nhạc raster. Tuy nhiên, khi được xem trong MapWindow GIS , dữ liệu dường như đi theo hướng ngược lại với điểm gốc được đặt phía trên bên trái , xuất hiện dưới dạng giá trị phía dưới bên trái .

Nói cách khác, dữ liệu được lật trên trục x của điểm gốc .

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

Tôi cũng nhận thấy khi tôi tính toán vị trí pixel cho một lat / lon nhất định , kết quả giá trị y trong một chỉ số âm, có vẻ như chính xác khi xem xét rằng mảng nằm từ phía trên bên trái sang phía dưới bên phải .

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)

Câu trả lời:


10

Tôi tìm thấy vấn đề ....

Vấn đề là trong việc xác định Geo_transform. Tôi đã có những điều sau đây:

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)

Tài liệu của Gdal không thực sự rõ ràng về những giá trị này là gì. (Xem SetGeoTransform ) Tìm kiếm xung quanh các internets tôi nhận thấy rằng các giá trị được truyền phải là (theo thứ tự):

  • top_left_x
  • cell_creen_meters
  • x_rotation
  • top_left_y
  • y_rotation
  • cell_height_meters

Điều đó có vẻ đúng, NHƯNG xem xét lại Hướng dẫn API GDAL Tôi nhận thấy rằng giá trị cuối cùng, cell_height_metersđược hiển thị được đưa ra trong một giá trị âm . Dường như đây là tất cả những gì cần thiết để xuất dữ liệu theo đúng hướng dự kiến.

Vì vậy, bây giờ tôi đã thay đổi dòng định nghĩa Geo_transform thành:

(Lưu ý thêm "-")

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

đây là cách truyền thống để đối phó với các thế giới hình ảnh như nguồn gốc ở phía trên bên trái và cách sử dụng địa lý ở phía dưới bên trái.
Ian Turton

Nó có ý nghĩa một khi bạn biết, nhưng tiếp cận vấn đề từ các ví dụ mã rất khó để tìm ra lý do. Tôi đã tìm thấy rằng các tài liệu ArcGIS có một số tài liệu tuyệt vời để giải thích về rasters: webhelp.esri.com/arcgisdesktop/9.3/...
monkut
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.