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

10

Я использую ArcGIS Desktop 10 с расширением Spatial Analyst.

Как объединить несколько растров в один, всегда выбирая случайным образом из значений перекрывающихся ячеек?

У меня есть изображение, которое может объяснить это лучше:

пример

Сэм
источник

Ответы:

7

Пик был создан для таких проблем. Думайте об этом как о версии «con» «switch» (или «case»), которая является реализацией алгебры карт «if ... else».

Например, если есть 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 в этом примере): их не должно быть.

Хотя в этом запущенном примере для выбора используются только три сетки, я написал его так, чтобы его можно было легко обобщить для любого числа сеток. При большом количестве сеток написание скрипта (для повторения повторяющихся операций) будет иметь неоценимое значение.

Whuber
источник
Знаете ли вы, как я мог игнорировать значения 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, если оно выбрано raster1, в противном случае выберите raster2. 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значения, так что кусок может быть опущен.

djq
источник
Я все еще работаю над своими навыками 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-го растра.

Надеюсь, что это имеет смысл :)

jareks
источник
Вы знаете, как выбирать из растров только значения? Например, на моей фигуре четыре 2 и два 3 перекрываются с NoData. Я хочу убедиться, что он выбирает только из этих растров со значениями в ячейке, а не NoData.
Сэм
Извините, что не отвечаю. Вы все еще боретесь с проблемой NoData?
jareks