Створення растра шляхом випадкового вибору значення комірки з декількох растров, що перекриваються?


10

Я використовую ArcGIS Desktop 10 з його розширенням Spatial Analyst.

Як можна об'єднати кілька растрових в одну, завжди вибираючи випадковим чином зі значень клітин, що перекриваються?

У мене є зображення, яке може пояснити це краще:

приклад

Відповіді:


7

Вибір створений для подібних проблем. Подумайте про це як про "перемикання" (або "випадок") версії "кон", що є реалізацією алгебри карти "якщо ... ще".

Якщо, наприклад, є 3 растри, що перекриваються, виглядатиме синтаксис (Python)

inPositionRaster = 1 + int(3 * CreateRandomRaster())
Pick(inPositionRaster, [inRas01, inRas02, inRas03])

Зверніть увагу, що pickіндексація починається з 1, а не з 0.


Редагувати

(див. нитку коментарів)

Щоб впоратися зі значеннями NoData, спочатку потрібно вимкнути обробку NoData ArcGIS. Зробіть це, створивши сітки, які мають спеціальне (але дійсне) значення замість NoData, наприклад 99999 (або що завгодно: але переконайтесь, що виберіть значення, яке більше, ніж будь-яке дійсне число, яке може з’явитися: це буде зручно пізніше) . Це вимагає використання запиту IsNull, як у

p01 = Con(IsNull(inRas01), 99999, inRas01)
p02 = Con(IsNull(inRas02), 99999, inRas01)
p03 = Con(IsNull(inRas03), 99999, inRas01)

Наприклад, розглянемо випадок цих однорядних сіток (NoData показано як "*"):

inRas01:  1  2 19  4  *  *  *  *
inRas02:  9  2  *  * 13 14  *  *
inRas03: 17  *  3  * 21  * 23  *

Результат - поставити 99999 на місце кожного "*".

Далі уявіть всі ці растрові як плоскі масиви дерев'яних блоків з NoData, що відповідають пропущеним блокам (отворам). Коли ви вертикально укладете ці растри, блоки потраплять у будь-які отвори під ними. Нам потрібна така поведінка, щоб уникнути вибору значень NoData: ми не хочемо вертикальних прогалин у стеках блоків. Порядок блоків у кожній вежі насправді не має значення. З цією метою ми можемо отримати кожну вежу, класифікуючи дані :

q01 = Rank(1, [p01, p02, p03])
q02 = Rank(2, [p01, p02, p03])
q03 = Rank(3, [p01, p02, p03])

У прикладі ми отримуємо

q01:      1     2     3     4    13    14    23 99999
q02:      9     2    19 99999    21 99999 99999 99999
q03:     17 99999 99999 99999 99999 99999 99999 99999

Зверніть увагу, що ранги - від найнижчого до найвищого, так що q01 містить найнижчі значення в кожному місці, q02 містить друге-найнижнє тощо. Коди NoData не починають відображатися, поки не будуть зібрані всі дійсні числа, оскільки ці коди мають більше , ніж будь-які дійсні числа.

Щоб уникнути вибору цих кодів NoData під час випадкового вибору, вам потрібно знати, скільки блоків складено в кожному місці: це говорить про те, скільки дійсних значень відбувається. Один із способів вирішити це - підрахувати кількість кодів NoData і відняти їх від загальної кількості сіток вибору:

n0 = 3 - EqualToFrequency(99999, [q01, q02, q03])

Це дає

n0:       3 2 2 1 2 1 1 0

Щоб обробити випадки, коли n = 0 (тому для вибору немає нічого), встановіть їх на NoData:

n = SetNull(n0 == 0, n0)

Тепер

n:        3 2 2 1 2 1 1 *

Це також гарантує, що ваші (тимчасові) коди NoData зникнуть під час остаточного розрахунку. Створення випадкових значень між 1 і n:

inPositionRaster = 1 + int(n * CreateRandomRaster())

Наприклад, може виглядати такий растр

inPositionRaster: 3 2 1 1 2 1 1 *

Усі його значення лежать між 1 і відповідним значенням у [n].

Виберіть значення точно, як і раніше:

selection = Pick(inPositionRaster, [q01, q02, q03])

Це призведе до

selection:       17  2  3  4 21 14 23  *

Щоб переконатися, що все в порядку, спробуйте вибрати всі вихідні комірки з кодом NoData (99999 у цьому прикладі): їх не повинно бути.

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


Чи знаєте ви, як я міг ігнорувати значення NoData з розрахунків (за допомогою Raster Calculator і Python)?
Сем

Сем, "Ігноруй", як саме? Я вважаю, що поведінка за замовчуванням полягає у виведенні NoData там, де одна або кілька вхідних растрових файлів є NoData (але я не повністю впевнений у цьому у випадку pick: якщо inPositionRaster і вибраний растр мають дійсні значення в комірці, то ймовірно результат для цієї комірки має бути значення вибраного растру, незалежно від того, що може містити будь-яка інша растра). Яку альтернативну поведінку ви думаєте?
whuber

Мені потрібно лише вибрати з усього числа значень. Скажімо, у мене три растри. Для комірки їх значення такі: 4,5, NoData. Я хочу, щоб у цієї осередку аборхівець мав 4 або 5, але ніколи не NoData.
Сем

У мене виникають проблеми з тим, щоб цей 1 + Int (n * CreateRandomRaster ()) працювати.
Сем

"Біда" в якому сенсі? Будь ласка, будьте конкретні!
whuber

4

Використання python та ArcGIS 10 та використання функції con, яка має такий синтаксис:

Con (in_conditional_raster, in_true_raster_or_constant, {in_false_raster_or_constant}, {where_clause})

Ідея тут полягає у тому, щоб перевірити, чи є значення у випадковому растрі менше 0,5, якщо він вибирається растровим1, інакше виберіть растровий2. NoData+ data = NoDataтому спочатку встановіть ці перекласифікуючі значення NoDataна 0:

import arcpy
from arcpy import env
from arcpy.sa import *
env.workspace = "C:/sapyexamples/data"

ras1_NoNull = Con(IsNull("elevation1"),0, "elevation1")  # remove NoData
ras2_NoNull = Con(IsNull("elevation2"),0, "elevation2")  # remove NoData
randRaster = CreateRandomRaster(100, 2, Extent(0, 0, 150, 150)) # raster generated between 0 and 1; 100 is seed value

outCon = Con(randRaster < 0.5, ras1_NoNull,  ras2_NoNull)  

outCon.save("C:/outcon.img")   # save raster

РЕДАКТУВАТИ: Щойно зрозумів, що ви не додаєте NoDataзначення, щоб шматок можна було залишити.


Я все ще працюю над своїми навичками Python. Чи є спосіб ввести це в Raster Calculator, який також виключав би значення NoData з процесу? У мене є 10 растрових, а в деяких є NoData, де інші мають значення.
Сем

Я думаю, що ви можете створити умови, використовуючи щось подібне, в растровому калькуляторіCon(IsNull(ras1), 0, ras2)
djq

На жаль, це насправді не виключає значень NoData: воно просто замінює їх нулями. У деяких випадках це може бути доречно, але тут, мабуть, немає!
whuber

хм, хороший пункт @whuber. То що означає виключити NoData? Це просто переконатися, що їх не вибирають, коли вибірково вибирають?
djq

Ось як я його інтерпретував (див. Мою відредаговану відповідь у цій темі), але це залишається гарним питанням. Таким чином, ігнорування значень ND призводить до вибору решти сіток з більшою ймовірністю, що може бути небажаним побічним ефектом. Все залежить від мети розрахунку.
whuber

1

Я б просто створив випадковий растр ( довідка ) однакового розміру та розміру комірок. Потім за допомогою CON ( довідки ) встановіть його для вибору значення з 1-го растру, якщо комірка з рандомізованого растру має значення <128 (якщо випадковий растр буде 0 - 255), інакше виберіть значення з другого растру.

Сподіваюся, що це має сенс :)


Чи знаєте ви, як вибрати лише з растрових значень? Наприклад, у моїй фігурі є чотири 2-х та два 3-х, які перетинаються з NoData. Я хочу переконатися, що він вибирає лише ті растри зі значеннями в комірці, а не NoData.
Сем

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