forked from tsamsonov/r-geo-course
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path12-SpatialAnalysisRaster.Rmd
248 lines (195 loc) · 21.4 KB
/
12-SpatialAnalysisRaster.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# Пространственный анализ 2. Растровые методы {#raster_analysis}
```{r setup, echo = FALSE, purl = FALSE, cache = FALSE, include=FALSE}
library(DT)
knitr::opts_knit$set(global.par = TRUE)
knitr::opts_knit$set(root.dir = "data/")
knitr::opts_chunk$set(warning=FALSE, collapse = TRUE)
```
[Программный код главы](https://github.com/tsamsonov/r-geo-course/blob/master/code/10-SpatialAnalysisRaster.R)
## Введение {#raster_intro}
Растровая модель данных представляет собой мощный инструмент абстракции пространственных распределений и выполнения пространственного анализа. На первый взгляд, растр обладает целым рядом ограничений по сравнению с векторной моделью: не позволяет оперировать отдельными объектами, их границами и так далее. Растровые карты и снимки мы часто оцифровываем, выделяя объекты, чтобы на основе них можно было что-то посчитать. Самые первые ГИС были исключительно растровыми, что сейчас воспринимается как архаизм.
Однако за ширмой ограниченности растровой модели кроются огромные аналитические возможности. Растровая модель обладает внутренней топологией: ее ячейки соприкасаются друг с другом, что позволяет моделировать непрерывные в пространстве и динамические явления (при которых происходит перемещение вещества, энергии или информации в пространстве). Поскольку ячейки растра имеют одинаковый размер, к ним можно применять однотипные операции, которые будут давать предсказуемый результат вне зависимости от конкретной локации в пределах растра. Это также позволяет сделать обработку растра очень быстро.
Существует классификация операций растрового анализа, введенная американским профессором Даной Томлином, которая объединяет их под общим названием "алгебра карт" или "растровая алгебра"^[Tomlin, C Dana. 2012. GIS and Cartographic Modeling. Second edition. Redlands, California: ESRI Press]. Предполагая, что обработке подвергается _каждая_ ячейка растра, данная классификация разделяет все операции по охвату относительно текущей ячейки
1. _Локальные_ --- анализируется одна ячейка растра или совпадающие в пространстве ячейки нескольких растров
2. _Фокальные_ --- анализируются все ячейки в окрестности. Окрестность может быть как фиксированной, так и расширенной (expanded), когда ее размер управляется внешними факторами, например множеством объектов, до которых требуется вычислить расстояние. Информация по соседним ячейкам может быть как из исходного растра, так и из внешнего. Фокальные методы алгебры карт также называются _методами анализа соседства_.
3. _Зональные_ --- анализируются все ячейки в пределах зон, определяемых извне (например, вторым растровым слоем).
4. _Глобальные_ --- анализируются все ячейки растра.
## Локальные операции {#raster_local}
Локальные операции связаны с алгебраическими преобразованиями значений в ячейках. Например, цифровую модель высот в футах можно перевести в цифровую модель высот в метрах. Для этого нужно значение в каждой ячейке умножить на $0.3048$. В локальных операциях могут участвовать несколько растров. Например, если у нас есть растровые поверхности плотности населения за разные года, мы можем вычесть одну поверхность из другой, чтобы получить поверхность изменений плотности, выяснить где она увеличилась, уменьшилась или осталось прежней. К локальным операциям относится также оверлей растров, при котором получается взвешенная сумма значений по нескольким растрам. И в том и в другом случае анализируются ячейки с нескольких растров, которые совпадают в пространстве.
В качестве примера определим мощность покровного оледенения в Антарктике и Гренландии, путем вычитание двух моделей [ETOPO1](https://www.ngdc.noaa.gov/mgg/global/), одна из которых показывает рельеф коренных пород (bedrock), а вторая --- видимый рельеф поверхности (ice surface):
```{r}
library(sp)
library(sf)
library(raster)
library(classInt)
# ЛОКАЛЬНЫЕ ОПЕРАЦИИ
# Вычисление толщины покровного оледенения
# Чтение данных
bed <- raster('etopo1_bed.tif')
ice <- raster('etopo1_ice.tif')
countries <- st_read('countries.gpkg')
borders <- countries %>% st_geometry()
# отображение данных
classes <- classIntervals(values(bed), 20)
brks <- classes$brks
nclass <- length(brks) - 1
plot(bed,
breaks = brks,
col = gray.colors(nclass),
main = 'ETOPO Bedrock',
legend = F)
plot(ice,
breaks = brks,
col = gray.colors(nclass),
main = 'ETOPO Ice surface',
legend = F)
# вычисление разности
ice.depth <- ice - bed
plot(ice.depth,
col = cm.colors(255),
main = 'Мощность покровного оледенения')
plot(borders,
border = 'black',
lwd = 0.5,
add = TRUE)
# сделаем пустыми все ячейки, в которых толщина льда равна нулю
ice.depth[ice.depth == 0] <- NA
plot(ice.depth,
col = cm.colors(255),
main = 'Мощность покровного оледенения')
plot(borders,
border = 'black',
lwd = 0.5,
add = TRUE)
```
## Фокальные операции {#raster_focal}
В фокальных операциях участвует не только сама ячейка или совпадающие с ней ячейки других растров, но также ячейки, находящиеся в некоторой окрестности (опять же, в одном или нескольких растрах одновременно). Данный вид анализа подразделяется на две категории: фокальный анализ с фиксированной окрестностью и с раширенной окрестностью.
### Фиксированная окрестность {#raster_focal_fixed}
В общем случае фиксированна окрестность может иметь различную форму, однако наиболее часто используется квадратная окрестность размером $3\times3$:

Фокальные операции с фиксированной окрестностью — привычное дело в обработке изображений. Они работают по принципу "плавающего окна". Выбранная окрестность (квадратная, круглая и т.д.) представляется в виде матрицы коэффициентов — так называемого ядра свёртки (convolution kernel). Далее эта матрица перемещается, позиционируясь последовательно над каждой ячейкой растра, и значение в этой ячейке заменяется на взвешенную сумму значений ячеек в окрестности, умноженных на соответствующие коэффициенты ядра свертки. Например, если ядро состоит из единиц, то будет посчитана обычная сумма.
С помощью фокального анализа можно выполнить сглаживание изображения, которое убирает из него мелкие детали (высокочастотные составляющие яркостного сигнала). В качестве такого изображения может быть цифровая модель рельефа или космический снимок. Чтобы выполнить сглаживание, коэффициенты должны быть такими, чтобы получаемая взвешенная сумма осредняла значения в соседних ячейках. Самый простой вариант --- это рассчитать среднее арифметическое. В этом случае коэффиценты ядра свертки будут равны $1/k$, где $k$ --- количество ячеек в окрестности. Для матрицы $3\times3$ они будут равны, соответственно $1/9$:
```{r}
# ФОКАЛЬНЫЕ ОПЕРАЦИИ
# Вырежем кусок из ЦМР
dem <- crop(ice, extent(-120, -75, 10, 40))
spplot(dem)
# Среднее
wgt <- matrix(c(1, 1, 1,
1, 1, 1,
1, 1, 1) / 9,
nrow = 3)
# на самом деле проще написать так:
# wgt <- matrix(1/9, 3, 3), но полная форма записана для наглядности
# выполним обработку ЦМР с помощью фокального фильтра
filtered <- focal(dem, w = wgt)
spplot(stack(dem, filtered),
names.attr=c('Исходный рельеф', 'Сглаживание средним'))
```
Более мягким эффектом сглаживания, который к тому же не нарушает дифференцируемость поверхности, является гауссово сглаживание. Коэффициенты в матрице Гаусса убывают от центральной ячейки к краям матрицы по закону Гаусса-Лапласа, что позволяет придать центральной ячейке более высокий вес по сравнению с ячейками, располагающимися на краю анализируемой окрестности:
```{r}
# Гауссово (параметр 0.5 - это стандартное отклонение в единицах измерения растра)
wgt <- focalWeight(dem, 0.5, "Gauss")
filtered <- focal(dem, wgt)
spplot(stack(dem, filtered),
names.attr=c('Исходный рельеф', 'Гауссово сглаживание'))
```
Еще одна интересная область применения фильтрации --- это обнаружение границ (change detection). Границы на изображении возникают в тех местах, где его яркость резко меняет свое значение (в одном или нескольких каналах). Например, на фотографии контур лица может быть распознан по перепаду яркости между его изображением и фоном (если он имеет существенно отличный цвет). Поскольку перепад яркости соответствует экстремальным значениям производной поверхности (отрицательным или положительным), его также можно определить путем фокального анализа, а затем отсечь ячейки растра, в которых значение этой производной по модулю превышает заданный порог (то есть, имеет необходимый контраст).
Рассмотрим, как можно выделить уступы континентального склона океана путем применения фильтра Собеля для выделения границ:
```{r}
# Матрица Собеля:
wgt <- matrix(c(1, 2, 1,
0, 0, 0,
-1,-2,-1) / 4,
nrow=3)
filtered <- focal(dem, wgt)
# Это поверхность производных:
plot(filtered,
col = gray.colors(128),
main = 'Производная поверхности')
# Отберем все ячейки, обладающие высокими значениями производных
faults <- (filtered < -1500) | (filtered > 1500)
faults[faults == 0] <- NA
# Визуализируем результат
plot(dem,
col = rev(rainbow(20)),
main = 'Уступы континентального склона',
legend = FALSE)
plot(faults,
col = 'black',
legend = FALSE,
add = TRUE)
```
Еще один распространненый случай использования фокальных операций --- это морфометрический анализ поверхностей. Квадратная окрестность $3\times3$ вокруг каждой ячейки формирует локальную поверхность, производные которой дают представление об уклоне, экспозиции и прочих морфометрических параметрах. Их можно вычислить с помощью функции `terrain()` из пакета `raster`:
```{r}
# Морфометрия рельефа — фиксированное соседство
dem <- raster('dem_fergana.tif')
spplot(dem)
# углы наклона
slope <- terrain(dem, opt = 'slope', unit = 'degrees')
spplot(slope,
col.regions = heat.colors(20),
names.attr=c('Углы наклона'))
# экспозиция
aspect <- terrain(dem, opt = 'aspect', unit = 'degrees')
spplot(aspect,
col.regions = rainbow(20),
names.attr=c('Экспозиции склона'))
```
Вычисление производных поверхности позволяет не только исследовать рельеф, но также строить его изображения. Например, хорошо знакомую всем по картам аналитическую отмыку рельефа (_hillshade_). Яркость поверхности в этом способе изображения зависит от угла между направлением на источник освещения (откуда светит Солнце) и нормалью к поверхности. Нормаль можно вычислить как напрямую через производные поверхности, так и восстановить на основе значений угла наклона и экспозиции в точке, что и используется в пакете __raster__. Обратите внимание на то, что для того чтобы повысить наглядность (контрастность) изображения, мы умножаем высоты рельефа на 20. Это стандартная практика для мелкомасштабных карт:
```{r}
# отмывка
slope2 <- terrain(dem * 20, opt = 'slope')
aspect2 <- terrain(dem * 20, opt = 'aspect')
# параметры angle и direction функции hillShade определяют азимут и высоту источника освещения:
hill <- hillShade(slope2, aspect2, angle = 45, direction = 315)
plot(hill,
col = gray.colors(128),
main = 'Отмывка рельефа')
```
### Расширенная окрестность {#raster_focal_extended}
Расширенность окрестности означает, что она определяется не фиксированным шаблоном, а условием, которое должно выполниться для того, чтобы анализ в ячейке считался выполненным. Типичный пример анализа на основе расширенной окрестности — это операции, основанные на вычислении расстояний на растровой матрице, такие как аллокация, опреление кратчайшего пути на поверхности сопростивления, и собственно, само вычисление расстояние.
В мелкомасштабных тематических атласах часто можно встретить карты доступности той или иной географической локации, которые в форме изолиний показывают время движения до ближайшего населенного пункта. Эти изолинии можно построить по растровой поверхности, в каждой ячейке которой зафиксировано расстояние до ближайшего населенного пункта.
Рассмотрим построение аналогичной поверхности на примере доступности станций метро (по расстоянию). Для этого нам понадобится представить растр в виде матрицы точек, рассчитать для этих точек расстояния до ближайших станций метро и присвоить эти значения выходному растру:
```{r}
# Определение Евклидовых расстояний — расширенное соседство
# Чтение данных
roads <- st_read("roads.gpkg") # Дороги
poi <- st_read("poi_point.gpkg") # Точки интереса
rayons <- st_read("boundary_polygon.gpkg") # Границы районов
stations <- st_read("metro_stations.gpkg") # Станции метро
water <- st_read("water_polygon.gpkg") # Водные объекты
# Создаем пустой растр с охватом, равным охвату станции
r <- raster(extent(stations), nrows = 200, ncols = 200)
# Конвертируем ячейки в точки
cells <- r %>% as("SpatialPoints") %>% st_as_sf() %>% st_set_crs(st_crs(stations))
# Вычисляем расстояния
d <- st_distance(stations, cells)
# Находим минимальное расстояние для каждой точки и заполняем
# полученными значениями текущее содержимое растра
r[] = apply(d, 2, min)
# Визуализируем результат
plot(r,
col = rev(heat.colors(100)),
main = 'Расстояние до ближайшей станции метро')
contour(r,
lwd = 0.5,
add= TRUE)
plot(water,
col = 'blue',
border = 'darkblue',
add = TRUE)
plot(roads,
lwd = 0.2,
col = 'black',
add = TRUE)
plot(stations,
pch = 20,
col = 'black',
add = TRUE)
```
## Зональные операции {#raster_zonal}
## Глобальные операции {#raster_global}
----
_Самсонов Т.Е._ **Визуализация и анализ географических данных на языке R.** М.: Географический факультет МГУ, 2017. DOI: 10.5281/zenodo.901911
----