Planchon & Darboux와 Wang 및 Liu 우울증 채우기 알고리즘에는 차이가 있습니까? 속도 외에?


11

실제 분석 경험을 바탕으로 DEM에서 우울증 (싱크)을 처리하고 채우는 속도 이외의 두 가지 우울증 채우기 알고리즘 사이에 차이가 있다면 누구나 말해 줄 수 있습니까?

디지털 고도 모델의 우울증을 채우기위한 빠르고 간단하며 다양한 알고리즘

Olivier Planchon, 프레드릭 다 부크

수 문학적 분석 및 모델링을위한 디지털 고도 모델에서 표면 함몰을 식별하고 채우는 효율적인 방법

왕과 리우

감사.

답변:


12

이론적으로 볼 때 우울증 채우기에는 솔루션이 하나만 있지만 솔루션에는 여러 가지 방법이있을 수 있기 때문에 다양한 우울증 채우기 알고리즘이 있습니다. 따라서 이론적으로 Planchon과 Darboux 또는 Wang and Liu 또는 다른 우울증 채우기 알고리즘으로 채워진 DEM은 나중에 동일하게 보입니다. 그러나 그렇지 않을 수도 있으며 몇 가지 이유가 있습니다. 첫째, 함몰을 채우기위한 솔루션은 하나 뿐이지 만, 채워진 함몰의 평평한 표면에 기울기를 적용하기위한 다양한 솔루션이 있습니다. 즉, 보통 우리는 우울증을 채우고 싶지 않을뿐만 아니라 채워진 우울증의 표면 위로 흐름을 강요하기를 원합니다. 일반적으로 매우 작은 그라디언트를 추가해야하며 1)이 작업을 수행하는 다양한 전략이 많이 있습니다 (다수의 우울증 채우기 알고리즘에 직접 내장되어 있음) 2) 작은 숫자를 처리하면 종종 작은 반올림 오류가 발생할 수 있습니다 채워진 DEM 사이의 차이로 나타납니다. 이 이미지를 살펴보십시오.

채워진 DEM의 고도 차이

소스 DEM에서 생성되었지만 Planchon 및 Darboux 알고리즘으로 채워진 우울증과 Wang 및 Liu 알고리즘으로 채워진 우울증으로 두 DEM 간의 '차이의 DEM'을 보여줍니다. 우울증 채우기 알고리즘은 둘 다 Whitebox GAT의 도구이므로 위의 답변에서 설명한 것과 다른 알고리즘 구현입니다. DEM의 차이는 모두 0.008m 미만이며 지형적 함몰 영역 내에 완전히 포함되어 있습니다 (즉, 함몰 내에 있지 않은 그리드 셀은 입력 DEM과 정확히 동일한 고도를 가짐). 8mm의 작은 값은 채우기 작업으로 남겨진 평평한 표면에 흐름을 적용하는 데 사용되는 작은 값을 반영하며 부동 소수점 값으로 작은 숫자를 나타낼 때 반올림 오차의 스케일에 의해 다소 영향을받을 수 있습니다. 위의 이미지에는 채워진 두 개의 DEM이 표시되지 않지만 범례 항목에서 예상 한 것과 정확히 동일한 범위의 고도 값을 가지고 있음을 알 수 있습니다.

그렇다면 위의 답변에서 DEM의 피크 및 기타 비 우울 지역의 고도 차이를 관찰하는 이유는 무엇입니까? 나는 그것이 알고리즘의 특정 구현으로 만 내려갈 수 있다고 생각합니다. 이러한 차이를 설명하기 위해 도구 내부에 무언가가 진행 중일 수 있으며 실제 알고리즘과 관련이 없습니다. 학술 논문의 알고리즘 설명과 실제 구현 사이의 격차가 GIS 내에서 데이터를 내부적으로 처리하는 방법의 복잡성과 결합 된 점을 감안하면 놀랍지 않습니다. 어쨌든이 흥미로운 질문을 해주셔서 감사합니다.

건배,

남자


정말 고마워 존! 언제나처럼 유익합니다. 나는 이제 단순히 우울증을 채우고 흐름을 보장하기 위해 최소 경사를 적용하는 것의 중요한 차이점을 이해합니다. 나는 그 두 가지 아이디어를 전에 혼란스럽게했다. 이 분석에 Whitebox를 사용하려고했지만 Planchon 및 Darboux 채우기를 실행할 때 유역 경계를 나타내는 NoData 값과 관련된 오류가 계속 발생한다는 것을 알고 싶습니다. 수정이 다가온다는 것을 알고 있습니다. 이를 피하기 위해 정사각형 DEM에서이 분석을 수행 했습니까? 다시 감사합니다.
traggatmot

1
+1 이와 같이 유익하고 사려 깊고 지식이 풍부한 답변을 읽는 것은 즐거움입니다.
whuber

5

나는 내 자신의 질문에 대답하려고 노력할 것입니다-던 던 던.

SAGA GIS를 사용하여 Planchon and Darboux (PD) 기반 충전 도구와 6 개의 다른 유역에 대한 Wang and Liu (WL) 기반 충전 도구를 사용하여 채워진 유역의 차이를 조사했습니다 (여기서는 두 가지 결과 집합 만 보여줍니다- 그것들은 6 가지 유역 모두에서 비슷했습니다.) 나는 "기반"이라고 말합니다. 왜냐하면 차이가 알고리즘에 의한 것인지 아니면 알고리즘의 특정 구현에 의한 것인지에 대한 질문이 항상 있기 때문입니다.

유역 DEM은 USGS 제공 유역 셰이프 파일을 사용하여 모자이크 된 NED 30m 데이터를 클리핑하여 생성되었습니다. 각 기본 DEM에 대해 두 도구가 실행되었습니다. 각 공구에 대해 최소 강제 기울기 옵션이 하나만 있으며 두 공구 모두에서 0.01로 설정되었습니다.

유역이 채워진 후 래스터 계산기를 사용하여 결과 그리드의 차이를 확인했습니다. 이러한 차이는 두 알고리즘의 다른 동작으로 인한 것입니다.

차이점 또는 차이가없는 이미지 (기본적으로 계산 된 차이 래스터)가 아래에 나와 있습니다. 차이 계산에 사용 된 공식은 다음과 같습니다. (((PD_Filled-WL_Filled) / PD_Filled) * 100)-셀 단위로 셀의 백분율 차이를 제공합니다. 색상이 회색 인 셀은 이제 차이를 보이며, 색상이 빨간색 일수록 결과 PD 높이가 더 높았고, 색상이 녹색 인 셀은 결과 WL 높이가 더 큼을 나타냅니다.

1 차 유역 : 맑은 유역, 와이오밍 여기에 이미지 설명을 입력하십시오

이 이미지의 전설은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

차이는 -0.0915 %에서 + 0.0910 % 사이입니다. 차이는 피크와 좁은 스트림 채널에 초점을 맞추는 것으로 보이며, WL 알고리즘은 채널에서 약간 높고 PD는 로컬 피크에서 약간 높습니다.

맑은 유역, 와이오밍, 줌 1 여기에 이미지 설명을 입력하십시오

맑은 유역, 와이오밍, 줌 2 여기에 이미지 설명을 입력하십시오

2 차 유역 : NH 위니 페소 키 강

여기에 이미지 설명을 입력하십시오

이 이미지의 전설은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

위니 페소 키 강, NH, 줌 1

여기에 이미지 설명을 입력하십시오

차이는 -0.323 %에서 + 0.315 % 사이입니다. 차이는 피크와 좁은 스트림 채널에 중점을 둔 것으로 보입니다 (전과 같이) WL 알고리즘은 채널에서 약간 높고 PD는 로컬 피크에서 약간 높습니다.

Sooooooo, 생각? 나에게 그 차이는 사소한 것 같지만 추가 계산에 영향을 미치지 않을 것입니다. 누구나 동의합니까? 이 6 개의 유역에 대한 워크 플로우를 완료하여 확인하고 있습니다.

편집 : 추가 정보 WL 알고리즘은 덜 뚜렷한 채널로 이어져 높은 지형 지수 값 (최종 파생 데이터 세트)을 유발하는 것으로 보입니다. 아래 왼쪽 이미지는 PD 알고리즘이고 오른쪽 이미지는 WL 알고리즘입니다.

여기에 이미지 설명을 입력하십시오

이 이미지는 같은 위치에서 오른쪽의 WL 그림에서 더 넓은 습한 영역 (더 많은 채널-빨간색, 높은 TI)에서 지형 지수의 차이를 보여줍니다. 왼쪽의 PD 그림에서 좁은 채널 (젖은 영역이 적음-적은 적색, 좁은 적색 영역, 낮은 TI 영역).

여기에 이미지 설명을 입력하십시오

또한, 여기 PD가 우울증을 처리하는 방법 (왼쪽)과 WL이 그것을 처리하는 방법 (오른쪽)이 있습니다.

여기에 이미지 설명을 입력하십시오

따라서 차이는 작지만 추가 분석을 통해 흘러가는 것처럼 보입니다.

누군가 관심이 있다면 내 Python 스크립트는 다음과 같습니다.

#! /usr/bin/env python

# ----------------------------------------------------------------------
# Create Fill Algorithm Comparison
# Author: T. Taggart
# ----------------------------------------------------------------------

import os, sys, subprocess, time



# function definitions
def runCommand_logged (cmd, logstd, logerr):
    p = subprocess.call(cmd, stdout=logstd, stderr=logerr)
# ----------------------------------------------------------------------


# ----------------------------------------------------------------------
# environmental variables/paths
if (os.name == "posix"):
    os.environ["PATH"] += os.pathsep + "/usr/local/bin"
else:
    os.environ["PATH"] += os.pathsep + "C:\program files (x86)\SAGA-GIS"
# ----------------------------------------------------------------------


# ----------------------------------------------------------------------
# global variables

WORKDIR    = "D:\TomTaggart\DepressionFillingTest\Ran_DEMs"

# This directory is the toplevel directoru (i.e. DEM_8)
INPUTDIR   = "D:\TomTaggart\DepressionFillingTest\Ran_DEMs"

STDLOG     = WORKDIR + os.sep + "processing.log"
ERRLOG     = WORKDIR + os.sep + "processing.error.log"
# ----------------------------------------------------------------------


# ----------------------------------------------------------------------
# open logfiles (append in case files are already existing)
logstd = open(STDLOG, "a")
logerr = open(ERRLOG, "a")
# ----------------------------------------------------------------------


# ----------------------------------------------------------------------
# initialize
t0      = time.time()
# ----------------------------------------------------------------------


# ----------------------------------------------------------------------
# loop over files, import them and calculate TWI

# this for loops walks through and identifies all the folder, sub folders, and so on.....and all the files, in the directory
# location that is passed to it - in this case the INPUTDIR
for dirname, dirnames, filenames in os.walk(INPUTDIR):
    # print path to all subdirectories first.
    #for subdirname in dirnames:
        #print os.path.join(dirname, subdirname)

    # print path to all filenames.
    for filename in filenames:
        #print os.path.join(dirname, filename)
        filename_front, fileext = os.path.splitext(filename)
        #print filename
        if filename_front == "w001001":
        #if fileext == ".adf":


            # Resetting the working directory to the current directory
            os.chdir(dirname)

            # Outputting the working directory
            print "\n\nCurrently in Directory: " + os.getcwd()

            # Creating new Outputs directory
            os.mkdir("Outputs")

            # Checks
            #print dirname + os.sep + filename_front
            #print dirname + os.sep + "Outputs" + os.sep + ".sgrd"

            # IMPORTING Files
            # --------------------------------------------------------------
            cmd = ['saga_cmd', '-f=q', 'io_gdal', 'GDAL: Import Raster',
                   '-FILES', filename,
                   '-GRIDS', dirname + os.sep + "Outputs" + os.sep + filename_front + ".sgrd",
                   #'-SELECT', '1',
                   '-TRANSFORM',
                   '-INTERPOL', '1'
                  ]

            print "Beginning to Import Files"

            try:
                runCommand_logged(cmd, logstd, logerr)

            except Exception, e:
                logerr.write("Exception thrown while processing file: " + filename + "\n")
                logerr.write("ERROR: %s\n" % e)

            print "Finished importing Files"

            # --------------------------------------------------------------


            # Resetting the working directory to the ouputs directory
            os.chdir(dirname + os.sep + "Outputs")



            # Depression Filling - Wang & Liu
            # --------------------------------------------------------------
            cmd = ['saga_cmd', '-f=q', 'ta_preprocessor', 'Fill Sinks (Wang & Liu)',
                   '-ELEV', filename_front + ".sgrd",
                   '-FILLED',  filename_front + "_WL_filled.sgrd",  # output - NOT optional grid
                   '-FDIR', filename_front + "_WL_filled_Dir.sgrd",  # output - NOT optional grid
                   '-WSHED', filename_front + "_WL_filled_Wshed.sgrd",  # output - NOT optional grid
                   '-MINSLOPE', '0.0100000', 
                               ]

            print "Beginning Depression Filling - Wang & Liu"

            try:
                runCommand_logged(cmd, logstd, logerr)

            except Exception, e:
                logerr.write("Exception thrown while processing file: " + filename + "\n")
                logerr.write("ERROR: %s\n" % e)

            print "Done Depression Filling - Wang & Liu"


            # Depression Filling - Planchon & Darboux
            # --------------------------------------------------------------
            cmd = ['saga_cmd', '-f=q', 'ta_preprocessor', 'Fill Sinks (Planchon/Darboux, 2001)',
                   '-DEM', filename_front + ".sgrd",
                   '-RESULT',  filename_front + "_PD_filled.sgrd",  # output - NOT optional grid
                   '-MINSLOPE', '0.0100000',
                               ]

            print "Beginning Depression Filling - Planchon & Darboux"

            try:
                runCommand_logged(cmd, logstd, logerr)

            except Exception, e:
                logerr.write("Exception thrown while processing file: " + filename + "\n")
                logerr.write("ERROR: %s\n" % e)

            print "Done Depression Filling - Planchon & Darboux"

            # Raster Calculator - DIff between Planchon & Darboux and Wang & Liu
            # --------------------------------------------------------------
            cmd = ['saga_cmd', '-f=q', 'grid_calculus', 'Grid Calculator',
                   '-GRIDS', filename_front + "_PD_filled.sgrd",
                   '-XGRIDS', filename_front + "_WL_filled.sgrd",
                   '-RESULT',  filename_front + "_DepFillDiff.sgrd",      # output - NOT optional grid
                   '-FORMULA', "(((g1-h1)/g1)*100)",
                   '-NAME', 'Calculation',
                   '-FNAME',
                   '-TYPE', '8',
                               ]

            print "Depression Filling - Diff Calc"

            try:
                runCommand_logged(cmd, logstd, logerr)

            except Exception, e:
                logerr.write("Exception thrown while processing file: " + filename + "\n")
                logerr.write("ERROR: %s\n" % e)

            print "Done Depression Filling - Diff Calc"

# ----------------------------------------------------------------------


# ----------------------------------------------------------------------
# finalize
logstd.write("\n\nProcessing finished in " + str(int(time.time() - t0)) + " seconds.\n")
logstd.close
logerr.close

# ----------------------------------------------------------------------

이 문제와 관련하여 SAGA 관리자에게 문의 했습니까?
reima

3

알고리즘 수준에서 두 알고리즘은 동일한 결과를 생성합니다.

왜 차이점이 생길 수 있습니까?

데이터 표현

알고리즘 중 하나 float(32 비트)를 사용하고 다른 알고리즘 double(64 비트)을 사용하는 경우 동일한 결과를 생성 할 것으로 기 대해서는 안됩니다. 마찬가지로 일부 구현에서는 부동 소수점 값이 정수 데이터 유형을 사용하므로 차이가 발생할 수 있음을 나타냅니다.

배수 시행

그러나 두 알고리즘 모두 흐름 방향을 결정하기 위해 지역화 된 방법을 사용하는 경우 배수되지 않는 평평한 영역을 생성합니다.

Planchon과 Darboux는 평평한 지역의 높이에 약간의 증분을 추가하여 배수를 시행하여이를 해결합니다. Barnes et al. (2014)의 논문 "래스터 디지털 입면 모델에서 평평한 표면에 배수 방향을 효율적으로 할당" 이 증분을 추가하면 실제로 증분이 너무 큰 경우 평평한 지역 외부의 배수가 자연스럽게 재 라우팅 될 수 있습니다. 해결책은 예를 들어 nextafter기능 을 사용하는 것입니다.

다른 생각들

Wang and Liu (2006)는 "우선 홍수 : 디지털 고도 모델을위한 최적의 우울증 채우기 및 유역 라벨링 알고리즘" 논문에서 논의 된 바와 같이 Priority-Flood 알고리즘의 변형입니다 .

Priority-Flood에는 정수 및 부동 소수점 데이터 모두에 시간 복잡성이 있습니다. 필자의 논문에서 셀을 우선 순위 대기열에 배치하지 않는 것이 알고리즘 성능을 향상시키는 좋은 방법이라고 지적했습니다. 같은 다른 저자 저우 등. (2016)Wei et al. (2018) 은이 아이디어를 사용하여 알고리즘의 효율성을 더욱 향상 시켰습니다. 이 모든 알고리즘의 소스 코드는 여기에서 확인할 수 있습니다 .

이를 염두에두고 Planchon and Darboux (2001) 알고리즘은 과학이 실패한 곳의 이야기입니다. 우선 홍수가 작동하는 동안 O (N) 정수 데이터와의 시간 O (N 로그 N) 부동 소수점 데이터에 시간, P & D는 O에서 (N 작동 1.5 ) 시간. 이는 DEM의 크기에 따라 기하 급수적으로 증가하는 큰 성능 차이로 해석됩니다.

우선 순위 홍수 우울증 충전을위한 Jenson 및 Domingue vs Planchon 및 Darboux vs Wang 및 Liu

2001 년 Ehlschlaeger, Vincent, Soille, Beucher, Meyer 및 Gratin은 Priority-Flood 알고리즘을 자세히 설명하는 5 개의 논문을 공동으로 발행했습니다. Planchon과 Darboux 및 그들의 검토 자들은이 모든 것을 놓치고 수십 배 느린 알고리즘을 발명했습니다. 현재 2018 년이며 여전히 더 나은 알고리즘을 구축하고 있지만 여전히 P & D가 사용되고 있습니다. 안타깝게 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.