Чи є різниця між алгоритмами заповнення депресії Планшона і Дарбу, Ванга та Лю? Крім швидкості?


11

Чи може хто-небудь сказати мені, виходячи з фактичного аналітичного досвіду, чи є різниця між цими двома алгоритмами заповнення депресії, крім швидкості, з якою вони обробляють і заповнюють поглиблення (раковини) в DEM?

Швидкий, простий і універсальний алгоритм для заповнення западин цифрових моделей висот

Олів'є Планшон, Фредерік Дарбу

і

Ефективний метод виявлення та заповнення поверхневих западин у цифрових моделях висот для гідрологічного аналізу та моделювання

Ван і Лю

Дякую.

Відповіді:


12

З теоретичної точки зору заповнення депресії має лише одне рішення, хоча існує безліч способів прийти до цього рішення, саме тому існує так багато різних алгоритмів заповнення депресії. Отже, теоретично DEM, заповнений або Планхоном і Дарбу, або Вангом і Лю, або будь-яким іншим алгоритмом заповнення депресії, повинен виглядати згодом однаково. Цілком ймовірно, що вони не стануть, і є кілька причин. По-перше, хоча існує лише одне рішення для заповнення западини, існує багато різних рішень для нанесення градієнта на плоску поверхню заповненої западини. Тобто зазвичай ми не просто хочемо заповнити депресію, але ми також хочемо примусити перетікати поверхню заповненої депресії. Це, як правило, включає додавання дуже малих градієнтів і 1) існує безліч різних стратегій для цього (багато з яких вбудовані в різні алгоритми заповнення депресії) і 2) робота з такими невеликими числами часто призводить до невеликих помилок округлення, які можуть проявлятись у відмінностях між заповненими DEM. Погляньте на це зображення:

Перепади висот у заповнених DEM

Він показує "DEM різниці" між двома DEM, обидва генеровані з вихідної DEM, але один з депресіями, заповненими за допомогою алгоритму Планхона і Дарбу, а другий за допомогою алгоритму Ванга і Лю. Я мушу сказати, що алгоритми заповнення депресії були обома інструментами всередині Whitebox GAT і тому є різними реалізаціями алгоритмів, ніж те, що ви описали у своїй відповіді вище. Зауважте, що різниці в DEM всі менше 0,008 м і що вони повністю містяться в межах топографічних западин (тобто осередки сітки, які не знаходяться в поглибленнях, мають точно такі ж висоти, що і вхідні DEM). Невелике значення 8 мм відображає крихітне значення, яке використовується для забезпечення руху потоку на плоских поверхнях, залишених операцією наповнення, а також, ймовірно, дещо впливає на масштаб помилок округлення при поданні таких малих чисел зі значеннями плаваючої точки. Ви не можете побачити два заповнені DEM, відображені на зображенні вище, але ви можете вказати з їхніх записів легенди, що вони також мають точно такий же діапазон значень висоти, як ви очікували.

Отже, чому ви б спостерігали різницю висот уздовж піків та інших недепресивних ділянок у DEM у своїй відповіді вище? Я думаю, що це дійсно могло б зводитися лише до конкретної реалізації алгоритму. Можливо, всередині цього інструмента відбувається щось для обліку цих відмінностей, і це не пов'язане з власне алгоритмом. Це не дивно для мене, враховуючи розрив між описом алгоритму в академічному документі та його реальною реалізацією у поєднанні зі складністю способів обробки даних у межах ГІС. Так чи інакше, дякую, що поставили це дуже цікаве запитання.

Ура,

Джон


Дякую, Джон! Інформаційний, як завжди. Тепер я нарешті зрозумів важливу різницю між простою заповненням депресії та примусовим застосуванням мінімального нахилу для забезпечення потоку. Раніше я сфотовував ці дві ідеї. Я хочу, щоб ви знали, що я намагався використовувати Whitebox для цього аналізу, але я продовжував стикатися з помилкою, пов’язаною зі значеннями NoData, що вистилають межу вододілу при запуску заповнення Planchon і Darboux - я знаю, що виправлення настає. Ви виконували цей аналіз на квадратній DEM, щоб уникнути цього? Знову дякую.
traggatmot

1
+1 Приємно читати інформативну, продуману, обізнану відповідь, як ця.
whuber

5

Я спробую відповісти на власне питання - dun dun dun.

Я використовував ГІС SAGA, щоб вивчити відмінності заповнених вододілів, використовуючи інструмент для заповнення на основі Планчона і Дарбу (PD) (а також інструмент для заповнення на основі Ван і Лю (WL) для 6 різних вододілів. (Тут я показую лише два випадки результатів - вони були схожими на всіх 6 вододілах) Я кажу "заснований", тому що завжди виникає питання, чи є розбіжності через алгоритм чи конкретну реалізацію алгоритму.

DEM вододілу генерували шляхом відсікання мозаїчних даних NED 30 м за допомогою USGS, наданих водороздільних форм. Для кожної базової DEM запускалися два інструменти; існує лише одна опція для кожного інструменту, мінімальний насичений нахил, який був встановлений в обох інструментах до 0,01.

Після заповнення вододілів я використовував растровий калькулятор, щоб визначити відмінності в отриманих сітках - ці відмінності повинні бути зумовлені лише різною поведінкою двох алгоритмів.

Зображення, що представляють відмінності або відсутність відмінностей (в основному, розраховані різниці різниці), представлені нижче. Формула, яка використовується для обчислення різниць, була такою: (((PD_F заповнений - WL_F заповнений) / PD_F заповнений) * 100) - дайте відсоткову різницю в комірці на основі клітин. Клітини сірого кольору виявляють тепер різницю, при цьому клітини червонішого кольору вказують на те, що результуюче підвищення ПД було більшим, а клітини зеленішими за кольором, що вказує на результуюче елевацію WL.

1-й вододіл: чистий вододіл, Вайомінг введіть тут опис зображення

Ось легенда для цих зображень:

введіть тут опис зображення

Відмінності коливаються лише від -0,0915% до + 0,0910%. Різниці, схоже, зосереджені навколо піків та вузьких каналів потоку, при цьому алгоритм WL трохи вище в каналах, а PD трохи вище навколо локалізованих вершин.

Ясний вододіл, Вайомінг, збільшення 1 введіть тут опис зображення

Ясний вододіл, Вайомінг, збільшення 2 введіть тут опис зображення

2-й вододіл: річка Вінніпесакі, штат Північна Кароліна

введіть тут опис зображення

Ось легенда для цих зображень:

введіть тут опис зображення

Річка Вінніпесакі, штат Північна Кароліна, масштаб 1

введіть тут опис зображення

Відмінності коливаються лише від -0,323% до + 0,315%. Різниці, схоже, зосереджені навколо піків і вузьких каналів потоку, з (як і раніше) алгоритм WL трохи вище в каналах, а PD трохи вище навколо локалізованих вершин.

Sooooooo, думки? На мій погляд, відмінності здаються тривіальними, ймовірно, не вплинуть на подальші розрахунки; хтось згоден? Я перевіряю, завершивши свій робочий процес для цих шести вододілів.

Редагувати: Більше інформації. Здається, що алгоритм WL призводить до більш широких менш чітких каналів, викликаючи високі значення топографічного індексу (мій кінцевий набір похідних даних). Зображення зліва внизу - алгоритм PD, зображення праворуч - алгоритм WL.

введіть тут опис зображення

Ці зображення показують різницю топографічного індексу в одних і тих же місцях - ширші вологі ділянки (більше каналу - червоніший, вищий TI) на зображенні WL праворуч; більш вузькі канали (менш волога область - менше червона, вузька червона зона, нижній рівень TI в області) на малюнку PD зліва.

введіть тут опис зображення

Крім того, ось як PD обробляв депресію і як WL обробляв її (праворуч) - помічайте піднятий помаранчевий (нижній топографічний індекс) відрізок / лінію, що перетинає депресію в заповненому 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-розрядний), не слід очікувати, що вони дадуть однаковий результат. Аналогічно, деякі реалізації представляють значення з плаваючою комою, використовуючи цілі типи даних, що також може призвести до відмінностей.

Забезпечення водовідведення

Однак обидва алгоритми дадуть плоскі ділянки, які не будуть стікати, якщо для визначення напрямків потоку використовується локалізований метод.

Планшон і Дарбу вирішують це, додаючи невеликий приріст до висоти рівнинної площі, щоб примусити осушення. Як обговорювалося в Barnes et al. Доповідь (2014) " Ефективне призначення напряму дренажу над плоскими поверхнями в растрових цифрових моделях висоти", додавання цього приросту може фактично спричинити неприродне перенапруження дренажу поза плоскою площею, якщо приріст занадто великий. Рішення полягає у використанні, наприклад, nextafterфункції.

Інші думки

Ван та Лю (2006) - це варіант алгоритму «Пріоритет-потоп», про який говорилося в моїй роботі «Пріоритетний затоп: Оптимальний алгоритм заповнення западини та вододілу для цифрових моделей висоти» .

Priority-Flood має часові складності як для цілих, так і для даних з плаваючою комою. У своїй роботі я зазначив, що уникнення розміщення комірок у черзі пріоритетів є хорошим способом підвищення продуктивності алгоритму. Інші автори, такі як Чжоу та ін. (2016) та Wei et al. (2018) використали цю ідею для подальшого підвищення ефективності алгоритму. Вихідний код для всіх цих алгоритмів доступний тут .

Зважаючи на це, алгоритм Планшона і Дарбу (2001) - це історія місця, де наука провалилася. У той час як Priority-Flood працює в О (N) час на цілі дані та О (N log N) час на даних з плаваючою комою, P&D працює в O (N 1,5 ) час. Це означає величезну різницю в продуктивності, яка зростає експоненціально з розміром DEM:

Дженсон і Домінгу в порівнянні з Плаччоном і Дарбу проти Ван і Лю для заповнення депресії "Пріоритетним потоком"

До 2001 року Елшлайгер, Вінсент, Сойль, Бюхер, Мейєр та Гратін спільно опублікували п'ять робіт, в яких детально описувався алгоритм «Пріоритет-потоп». Планшон і Дарбу та їх рецензенти пропустили все це і винайшли алгоритм, який набирав на повільність. Зараз 2018 рік, і ми все ще будуємо кращі алгоритми, але P&D все ще використовується. Я думаю, що це прикро.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.