GDAL - Thực hiện phân tích đường dẫn chi phí tối thiểu đơn giản


8

Tôi đang nghiên cứu các phương pháp để thực hiện phân tích đường dẫn đơn giản với chi phí thấp nhất với gdal. Nói một cách đơn giản, ý tôi là sử dụng độ dốc của dem làm yếu tố chi phí duy nhất.

Tôi muốn sử dụng các ràng buộc python hoặc .net, nhưng sẽ mất bất cứ điều gì. Bất cứ ai có thể đề nghị bất kỳ hướng dẫn tốt hoặc tương tự?


3
Đối với các câu hỏi phân tích, có lẽ tốt hơn nên sử dụng một hệ thống GIS thay vì thư viện trừu tượng hóa định dạng dữ liệu ...
markusN

2
Vì tò mò, ứng dụng là gì? Thật khó để nghĩ bất cứ điều gì mà độ dốc của DEM sẽ là một ủy quyền thực tế cho chi phí đi lại. Bạn có chắc chắn đây là những gì bạn cần? Sẽ thật đáng tiếc nếu sau khi nỗ lực viết mã này, bạn phát hiện ra nó không thực sự giải quyết vấn đề của bạn!
whuber

Độ dốc có thể hữu ích như một chi phí đi lại nếu bạn đang mô hình một mô hình phân tán phụ thuộc vào trọng lực của một loại nào đó, mặc dù tôi cũng mong đợi một số yếu tố khác thay vì chỉ là độ dốc.
MappaGnosis

Ngoài ra, độ dốc thường hiển thị độ dốc tối đa tại mỗi ô, ngay cả khi tuyến đường không đi trực tiếp xuống dốc hoặc lên dốc.
Matthew Snape

Câu trả lời:


8

Các kịch bản sau đây thực hiện một phân tích đường dẫn chi phí ít nhất. Các tham số đầu vào là một raster bề mặt chi phí (ví dụ độ dốc) và tọa độ bắt đầu và dừng. Một raster với đường dẫn đã tạo được trả về. Nó đòi hỏi thư viện skimage và GDAL.

Ví dụ: đường dẫn chi phí ít nhất giữa điểm 1 và điểm 2 được tạo dựa trên raster dốc: nhập mô tả hình ảnh ở đây

import gdal, osr
from skimage.graph import route_through_array
import numpy as np


def raster2array(rasterfn):
    raster = gdal.Open(rasterfn)
    band = raster.GetRasterBand(1)
    array = band.ReadAsArray()
    return array  

def coord2pixelOffset(rasterfn,x,y):
    raster = gdal.Open(rasterfn)
    geotransform = raster.GetGeoTransform()
    originX = geotransform[0]
    originY = geotransform[3] 
    pixelWidth = geotransform[1] 
    pixelHeight = geotransform[5]
    xOffset = int((x - originX)/pixelWidth)
    yOffset = int((y - originY)/pixelHeight)
    return xOffset,yOffset

def createPath(CostSurfacefn,costSurfaceArray,startCoord,stopCoord):   

    # coordinates to array index
    startCoordX = startCoord[0]
    startCoordY = startCoord[1]
    startIndexX,startIndexY = coord2pixelOffset(CostSurfacefn,startCoordX,startCoordY)

    stopCoordX = stopCoord[0]
    stopCoordY = stopCoord[1]
    stopIndexX,stopIndexY = coord2pixelOffset(CostSurfacefn,stopCoordX,stopCoordY)

    # create path
    indices, weight = route_through_array(costSurfaceArray, (startIndexY,startIndexX), (stopIndexY,stopIndexX),geometric=True,fully_connected=True)
    indices = np.array(indices).T
    path = np.zeros_like(costSurfaceArray)
    path[indices[0], indices[1]] = 1
    return path

def array2raster(newRasterfn,rasterfn,array):
    raster = gdal.Open(rasterfn)
    geotransform = raster.GetGeoTransform()
    originX = geotransform[0]
    originY = geotransform[3] 
    pixelWidth = geotransform[1] 
    pixelHeight = geotransform[5]
    cols = array.shape[1]
    rows = array.shape[0]

    driver = gdal.GetDriverByName('GTiff')
    outRaster = driver.Create(newRasterfn, cols, rows, gdal.GDT_Byte)
    outRaster.SetGeoTransform((originX, pixelWidth, 0, originY, 0, pixelHeight))
    outband = outRaster.GetRasterBand(1)
    outband.WriteArray(array)
    outRasterSRS = osr.SpatialReference()
    outRasterSRS.ImportFromWkt(raster.GetProjectionRef())
    outRaster.SetProjection(outRasterSRS.ExportToWkt())
    outband.FlushCache()    

def main(CostSurfacefn,outputPathfn,startCoord,stopCoord):

    costSurfaceArray = raster2array(CostSurfacefn) # creates array from cost surface raster

    pathArray = createPath(CostSurfacefn,costSurfaceArray,startCoord,stopCoord) # creates path array

    array2raster(outputPathfn,CostSurfacefn,pathArray) # converts path array to raster


if __name__ == "__main__":
    CostSurfacefn = 'CostSurface.tif'
    startCoord = (345387.871,1267855.277)
    stopCoord = (345479.425,1267799.626)
    outputPathfn = 'Path.tif'
    main(CostSurfacefn,outputPathfn,startCoord,stopCoord)

Tôi thích câu trả lời của bạn. Làm thế nào để bạn đối phó với ví dụ như hồ trong đó giá trị chi phí là như nhau cho một diện tích lớn hơn. Con đường của tôi đi qua một cái hồ và những khúc quanh co như một con rắn cho đến khi khu vực này được bao phủ trước khi nó tiếp tục như mong đợi? Cảm ơn.
Michael

Tôi đã không làm việc này trong một thời gian dài. Bạn có thể nghĩ về điều này rồi, nhưng tôi sẽ chỉ đặt chi phí cho hồ thực sự cao. Lối này nên tránh hồ, phải không?
ustroetz

Vâng, tôi đặt hồ chỉ là hơn 0 một chút, theo cách đó có một chi phí và sự uốn khúc biến mất.
Michael

3

Bạn có thể sử dụng thuật toán tìm kiếm A * bằng cách sử dụng độ dốc làm chi phí giữa các nút được tạo. Để xem một hình dung nhanh về những gì trông giống như:

Một ngôi sao hoạt hình

Xem A * Thuật toán tìm kiếm (Wiki)Python A * Thuật toán tìm kiếm (SO)

để hiểu A *.

Đối với bản đồ độ dốc có các tùy chọn ngoài kia - Đây là một.

Với bản đồ độ dốc (raster), bạn có thể nhận được các giá trị chi phí từ nó với GDAL.


2
Bạn có thể giải thích làm thế nào để tạo độ dốc cho biểu đồ để nó có thể được sử dụng trong Mã thuật toán tìm kiếm Python A * mà bạn đã chỉ ra không? Tôi biết làm thế nào để lấy giá trị ra khỏi raster với GDAL. nhưng như những gì tôi sẽ lưu trữ nó để sử dụng nó như một biểu đồ (ví dụ: Từ điển?)?
ustroetz
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.