|
10 | 10 | "\n",
|
11 | 11 | "Xarray-spatial's Remote Sensing tools provide a range of functions pertaining to remote sensing data such as satellite imagery. A range of functions are available to calculate various vegetation and environmental parameters from the range of band data available for an area. These functions accept and output data in the form of xarray.DataArray rasters.\n",
|
12 | 12 | "\n",
|
13 |
| - "[Generate terrain](#Generate-Terrain-Data) \n", |
14 |
| - "[Bump](#Bump) \n", |
15 |
| - "[NDVI](#NDVI) \n", |
| 13 | + "[True Color](#True-Color) \n", |
| 14 | + "[Vegetation Index](#Vegetation-Index): [NDVI](#NDVI), [SAVI](#SAVI), [ARVI](#ARVI), [EVI](#EVI) \n", |
| 15 | + "[Green Chlorophyll Index - GCI](#Green-Chlorophyll-Index-(GCI)) \n", |
| 16 | + "[Normalized Burn Ratio](#Normalized-Burn-Ratio): [NBR](#NBR), [NBR2](#NBR2) \n", |
| 17 | + "[Normalized Difference Moisture Index - NDMI](#Normalized-Difference-Moisture-Index-(NDMI)) \n", |
| 18 | + "[Structure Insensitive Pigment Index - SIPI](#Structure-Insensitive-Pigment-Index-(SIPI)) \n", |
| 19 | + "[Enhanced Built-Up and Bareness Index - EBBI](#Enhanced-Built-Up-and-Bareness-Index-(EBBI)) \n", |
| 20 | + "[Bump Mapping](#Bump-Mapping) \n", |
16 | 21 | "\n",
|
17 | 22 | "-----------\n"
|
18 | 23 | ]
|
|
21 | 26 | "cell_type": "markdown",
|
22 | 27 | "metadata": {},
|
23 | 28 | "source": [
|
24 |
| - "### Load data" |
| 29 | + "## Load data" |
25 | 30 | ]
|
26 | 31 | },
|
27 | 32 | {
|
|
124 | 129 | "cell_type": "markdown",
|
125 | 130 | "metadata": {},
|
126 | 131 | "source": [
|
127 |
| - "### True Color\n", |
| 132 | + "## True Color\n", |
128 | 133 | "\n",
|
129 | 134 | "Now we're ready to apply some xarray-spatial functions. \n",
|
130 | 135 | "\n",
|
|
137 | 142 | "metadata": {},
|
138 | 143 | "outputs": [],
|
139 | 144 | "source": [
|
140 |
| - "import xrspatial.multispectral as ms\n", |
| 145 | + "from xrspatial.multispectral import true_color\n", |
141 | 146 | "\n",
|
142 |
| - "ms.true_color(layers[\"red\"], layers[\"green\"], layers[\"blue\"])" |
| 147 | + "true_color_agg = true_color(layers[\"red\"], layers[\"green\"], layers[\"blue\"])\n", |
| 148 | + "Image(true_color_agg)" |
143 | 149 | ]
|
144 | 150 | },
|
145 | 151 | {
|
146 | 152 | "cell_type": "markdown",
|
147 | 153 | "metadata": {},
|
148 | 154 | "source": [
|
149 |
| - "## NDVI\n", |
| 155 | + "## Vegetation Index\n", |
| 156 | + "\n", |
| 157 | + "### NDVI\n", |
150 | 158 | "\n",
|
151 | 159 | "The [Normalized Difference Vegetation Index](https://en.wikipedia.org/wiki/Normalized_difference_vegetation_index) (NDVI) is a metric designed to detect regions with vegetation by measuring the difference between near-infrared (NIR) light (which vegetation reflects) and red light (which vegetation absorbs).\n",
|
152 | 160 | "\n",
|
153 |
| - "The NDVI ranges over [-1,+1], where `-1` means more \"Red\" radiation while `+1` means more \"NIR\" radiation. NDVI values close to +1.0 suggest areas dense with active green foliage, while strongly negative values suggest cloud cover or snow, and values near zero suggest open water, urban areas, or bare soil. \n", |
| 161 | + "The NDVI ranges over [-1,+1], where `-1` means more \"Red\" radiation while `+1` means more \"NIR\" radiation. NDVI values close to +1.0 suggest areas dense with active green foliage, while strongly negative values suggest cloud cover or snow, and values near zero suggest open water, urban areas, or bare soil.\n", |
154 | 162 | "\n",
|
155 |
| - "For our synthetic example here, we don't have access to NIR measurements, but we can approximate the results for demonstration purposes by using the green and blue channels of a colormapped image, as those represent a difference in wavelengths similar to NIR vs. Red." |
| 163 | + "Let's apply `xrspatial.multispectral.ndvi` to the satellite band images from above." |
| 164 | + ] |
| 165 | + }, |
| 166 | + { |
| 167 | + "cell_type": "code", |
| 168 | + "execution_count": null, |
| 169 | + "metadata": {}, |
| 170 | + "outputs": [], |
| 171 | + "source": [ |
| 172 | + "from xrspatial.multispectral import ndvi\n", |
| 173 | + "\n", |
| 174 | + "ndvi_agg = ndvi(nir_agg=layers[\"nir\"], red_agg=layers[\"red\"])" |
156 | 175 | ]
|
157 | 176 | },
|
158 | 177 | {
|
159 | 178 | "cell_type": "markdown",
|
160 | 179 | "metadata": {},
|
161 | 180 | "source": [
|
162 |
| - "Let's start by applying `xrspatial.ndvi` to the satellite band images from above." |
| 181 | + "### SAVI\n", |
| 182 | + "\n", |
| 183 | + "`xrspatial.multispectral.savi` also computes the vegetation index from the red and nir bands, but it applies a correction factor for the soil brightness.\n", |
| 184 | + "\n", |
| 185 | + "Let's try applying that to our bands from above." |
163 | 186 | ]
|
164 | 187 | },
|
165 | 188 | {
|
|
168 | 191 | "metadata": {},
|
169 | 192 | "outputs": [],
|
170 | 193 | "source": [
|
171 |
| - "import xrspatial.multispectral as ms\n", |
172 |
| - "from xrspatial.multispectral import ndvi\n", |
173 | 194 | "from xrspatial.multispectral import savi\n",
|
174 | 195 | "\n",
|
175 |
| - "nir = layers[\"nir\"]\n", |
176 |
| - "# nir.data = nir.data.astype('float')\n", |
| 196 | + "savi_agg = savi(layers[\"nir\"], layers[\"red\"])" |
| 197 | + ] |
| 198 | + }, |
| 199 | + { |
| 200 | + "cell_type": "markdown", |
| 201 | + "metadata": {}, |
| 202 | + "source": [ |
| 203 | + "### ARVI\n", |
177 | 204 | "\n",
|
178 |
| - "red = layers[\"red\"]\n", |
179 |
| - "# red.data = red.data.astype('float')\n", |
| 205 | + "`xrspatial.multispectral.arvi` computes the Atmospherically Resistant vegetation index from the blue, red and nir bands. It applies molecular and ozone correction with no further need for aerosol correction, except for dust conditions.\n", |
180 | 206 | "\n",
|
| 207 | + "Let's try applying that to our bands data." |
| 208 | + ] |
| 209 | + }, |
| 210 | + { |
| 211 | + "cell_type": "code", |
| 212 | + "execution_count": null, |
| 213 | + "metadata": {}, |
| 214 | + "outputs": [], |
| 215 | + "source": [ |
| 216 | + "from xrspatial.multispectral import arvi\n", |
181 | 217 | "\n",
|
182 |
| - "nir_img = shade(nir, cmap=[\"purple\", \"black\", \"green\"])\n", |
183 |
| - "nir_img.name = \"nir\"\n", |
| 218 | + "arvi_agg = arvi(layers[\"nir\"], layers[\"red\"], layers[\"blue\"])" |
| 219 | + ] |
| 220 | + }, |
| 221 | + { |
| 222 | + "cell_type": "markdown", |
| 223 | + "metadata": {}, |
| 224 | + "source": [ |
| 225 | + "### EVI\n", |
184 | 226 | "\n",
|
185 |
| - "red_img = shade(red, cmap=[\"purple\", \"black\", \"green\"])\n", |
186 |
| - "red_img.name = \"red\"\n", |
| 227 | + "`xrspatial.multispectral.evi` computes the Enhanced Vegetation Index. It allows for importved sensitivity in high biomass regions, de-coupling of the canopy background signal and reduction of atmospheric influences. The function uses nir, red and blue bands.\n", |
187 | 228 | "\n",
|
188 |
| - "ndvi_img = ndvi(nir_agg=nir, red_agg=red)\n", |
189 |
| - "ndvi_img = shade(ndvi_img, cmap=[\"purple\", \"black\", \"green\"])\n", |
190 |
| - "ndvi_img.name = \"ndvi\"\n", |
| 229 | + "Let's try applying that to our bands data." |
| 230 | + ] |
| 231 | + }, |
| 232 | + { |
| 233 | + "cell_type": "code", |
| 234 | + "execution_count": null, |
| 235 | + "metadata": {}, |
| 236 | + "outputs": [], |
| 237 | + "source": [ |
| 238 | + "from xrspatial.multispectral import evi\n", |
191 | 239 | "\n",
|
192 |
| - "Images(nir_img, red_img, ndvi_img)" |
| 240 | + "evi_agg = evi(layers[\"nir\"], layers[\"red\"], layers[\"blue\"])" |
193 | 241 | ]
|
194 | 242 | },
|
195 | 243 | {
|
196 | 244 | "cell_type": "markdown",
|
197 | 245 | "metadata": {},
|
198 | 246 | "source": [
|
199 |
| - "Now, substituting the blue and green bands, we get the following image." |
| 247 | + "### Visualize all vegetation indexes" |
200 | 248 | ]
|
201 | 249 | },
|
202 | 250 | {
|
|
205 | 253 | "metadata": {},
|
206 | 254 | "outputs": [],
|
207 | 255 | "source": [
|
208 |
| - "tf.shade(\n", |
209 |
| - " ndvi(nir_agg=layers[\"green\"], red_agg=layers[\"blue\"]),\n", |
210 |
| - " how=\"eq_hist\",\n", |
211 |
| - " cmap=[\"purple\", \"black\", \"green\"],\n", |
212 |
| - ")" |
| 256 | + "vegetation_index_aggs = [ndvi_agg, savi_agg, arvi_agg, evi_agg]\n", |
| 257 | + "images = [shade(agg, cmap=['purple', 'black', 'green']) for agg in vegetation_index_aggs]\n", |
| 258 | + "\n", |
| 259 | + "Images(*images)" |
213 | 260 | ]
|
214 | 261 | },
|
215 | 262 | {
|
216 | 263 | "cell_type": "markdown",
|
217 | 264 | "metadata": {},
|
218 | 265 | "source": [
|
219 |
| - "As you can see, we get a similar image as before, though it is not as well-defined." |
| 266 | + "## Green Chlorophyll Index (GCI)\n", |
| 267 | + "\n", |
| 268 | + "`xrspatial.gci` computes the Green Chlorophyll Index. It can be used to estimate the content of leaf chorophyll and predict the physiological state of vegetation and plant health. The function uses nir and green band data.\n", |
| 269 | + "\n", |
| 270 | + "Let's apply that to our bands data." |
| 271 | + ] |
| 272 | + }, |
| 273 | + { |
| 274 | + "cell_type": "code", |
| 275 | + "execution_count": null, |
| 276 | + "metadata": {}, |
| 277 | + "outputs": [], |
| 278 | + "source": [ |
| 279 | + "from xrspatial.multispectral import gci\n", |
| 280 | + "\n", |
| 281 | + "gci_agg = gci(layers[\"nir\"], layers[\"green\"])\n", |
| 282 | + "shade(gci_agg)" |
220 | 283 | ]
|
221 | 284 | },
|
222 | 285 | {
|
223 | 286 | "cell_type": "markdown",
|
224 | 287 | "metadata": {},
|
225 | 288 | "source": [
|
226 |
| - "### SAVI\n", |
| 289 | + "## Normalized Burn Ratio\n", |
227 | 290 | "\n",
|
228 |
| - "`xrspatial.savi` also computes the vegetation index from the red and nir bands, but it applies a correction factor for the soil brightness.\n", |
| 291 | + "`xrspatial.multispectral` provides 2 tools for computing the Normalized Burn Ratio. `xrspatial.multispectral.nbr` is to identify burned areas and provide a measure of burn severity while `xrspatial.multispectral.nbr2` modifies the Normalized Burn Ratio (NBR) to highlight water sensitivity in vegetation and may be useful in post-fire recovery studies.\n", |
229 | 292 | "\n",
|
230 |
| - "Let's try applying that to our bands from above." |
| 293 | + "\n", |
| 294 | + "### NBR\n", |
| 295 | + "`xrspatial.multispectral.nbr` uses NIR and SWIR2 band data. Let's calculate NBR using the our example data." |
231 | 296 | ]
|
232 | 297 | },
|
233 | 298 | {
|
|
236 | 301 | "metadata": {},
|
237 | 302 | "outputs": [],
|
238 | 303 | "source": [
|
239 |
| - "shade(savi(layers[\"nir\"], layers[\"red\"]))" |
| 304 | + "from xrspatial.multispectral import nbr\n", |
| 305 | + "\n", |
| 306 | + "nbr_agg = nbr(layers[\"nir\"], layers[\"swir2\"])\n", |
| 307 | + "shade(nbr_agg)" |
| 308 | + ] |
| 309 | + }, |
| 310 | + { |
| 311 | + "cell_type": "markdown", |
| 312 | + "metadata": {}, |
| 313 | + "source": [ |
| 314 | + "### NBR2\n", |
| 315 | + "`xrspatial.multispectral.nbr2` uses SWIR1 and SWIR2 band data. Let's calculate NBR2 using the our example data." |
| 316 | + ] |
| 317 | + }, |
| 318 | + { |
| 319 | + "cell_type": "code", |
| 320 | + "execution_count": null, |
| 321 | + "metadata": {}, |
| 322 | + "outputs": [], |
| 323 | + "source": [ |
| 324 | + "from xrspatial.multispectral import nbr2\n", |
| 325 | + "\n", |
| 326 | + "nbr2_agg = nbr2(layers[\"swir1\"], layers[\"swir2\"])\n", |
| 327 | + "shade(nbr2_agg)" |
| 328 | + ] |
| 329 | + }, |
| 330 | + { |
| 331 | + "cell_type": "markdown", |
| 332 | + "metadata": {}, |
| 333 | + "source": [ |
| 334 | + "## Normalized Difference Moisture Index (NDMI) \n", |
| 335 | + "\n", |
| 336 | + "`xrspatial.multispectral.ndmi` calculates the Normalized Difference Moisture Index. It can be used to determine vegetation water content. The function uses NIR and SWIR1 band data." |
| 337 | + ] |
| 338 | + }, |
| 339 | + { |
| 340 | + "cell_type": "code", |
| 341 | + "execution_count": null, |
| 342 | + "metadata": {}, |
| 343 | + "outputs": [], |
| 344 | + "source": [ |
| 345 | + "from xrspatial.multispectral import ndmi\n", |
| 346 | + "\n", |
| 347 | + "ndmi_agg = ndmi(layers[\"nir\"], layers[\"swir1\"])\n", |
| 348 | + "shade(ndmi_agg)" |
| 349 | + ] |
| 350 | + }, |
| 351 | + { |
| 352 | + "cell_type": "markdown", |
| 353 | + "metadata": {}, |
| 354 | + "source": [ |
| 355 | + "## Structure Insensitive Pigment Index (SIPI) \n", |
| 356 | + "\n", |
| 357 | + "`xrspatial.multispectral.sipi` calculates the Structure Insensitive Pigment Index which helpful in early disease detection in vegetation. The function uses NIR, red and blue band data." |
| 358 | + ] |
| 359 | + }, |
| 360 | + { |
| 361 | + "cell_type": "code", |
| 362 | + "execution_count": null, |
| 363 | + "metadata": {}, |
| 364 | + "outputs": [], |
| 365 | + "source": [ |
| 366 | + "from xrspatial.multispectral import sipi\n", |
| 367 | + "\n", |
| 368 | + "sipi_agg = sipi(layers[\"nir\"], layers[\"red\"], layers[\"blue\"])\n", |
| 369 | + "shade(sipi_agg)" |
240 | 370 | ]
|
241 | 371 | },
|
242 | 372 | {
|
243 | 373 | "cell_type": "markdown",
|
244 | 374 | "metadata": {},
|
245 | 375 | "source": [
|
246 |
| - "For the next few functions, we'll experiment with an artificial terrain. We'll use xarray-spatial's `generate_terrain` along with datashader's Canvas to smooth thing" |
| 376 | + "## Enhanced Built-Up and Bareness Index (EBBI)\n", |
| 377 | + "\n", |
| 378 | + "`xrspatial.multispectral.sipi` computes the Enhanced Built-Up and Bareness Index (EBBI) which allows for easily distinguishing between built-up and bare land areas. The function uses red, SWIR, and TIR band data." |
| 379 | + ] |
| 380 | + }, |
| 381 | + { |
| 382 | + "cell_type": "code", |
| 383 | + "execution_count": null, |
| 384 | + "metadata": {}, |
| 385 | + "outputs": [], |
| 386 | + "source": [ |
| 387 | + "from xrspatial.multispectral import ebbi\n", |
| 388 | + "\n", |
| 389 | + "ebbi_agg = ebbi(layers[\"red\"], layers[\"swir1\"], layers[\"tir1\"])\n", |
| 390 | + "shade(ebbi_agg)" |
247 | 391 | ]
|
248 | 392 | },
|
249 | 393 | {
|
250 | 394 | "cell_type": "markdown",
|
251 | 395 | "metadata": {},
|
252 | 396 | "source": [
|
253 |
| - "#### Generate Terrain" |
| 397 | + "## Bump Mapping\n", |
| 398 | + "\n", |
| 399 | + "For the next few functions, we'll experiment with an artificial terrain. We'll use xarray-spatial's `generate_terrain` along with datashader's Canvas to smooth thing.\n", |
| 400 | + "\n", |
| 401 | + "### Generate Terrain" |
254 | 402 | ]
|
255 | 403 | },
|
256 | 404 | {
|
|
319 | 467 | "cell_type": "markdown",
|
320 | 468 | "metadata": {},
|
321 | 469 | "source": [
|
322 |
| - "## Bump\n", |
| 470 | + "### Bump\n", |
323 | 471 | "\n",
|
324 | 472 | "Bump mapping is a cartographic technique that can be used to create the appearance of trees or other land features, which is useful when synthesizing human-interpretable images from source data like land use classifications.\n",
|
325 | 473 | "\n",
|
|
387 | 535 | ],
|
388 | 536 | "metadata": {
|
389 | 537 | "kernelspec": {
|
390 |
| - "display_name": "Python 3", |
| 538 | + "display_name": "Python 3 (ipykernel)", |
391 | 539 | "language": "python",
|
392 | 540 | "name": "python3"
|
393 | 541 | },
|
|
401 | 549 | "name": "python",
|
402 | 550 | "nbconvert_exporter": "python",
|
403 | 551 | "pygments_lexer": "ipython3",
|
404 |
| - "version": "3.8.5" |
| 552 | + "version": "3.9.14" |
405 | 553 | }
|
406 | 554 | },
|
407 | 555 | "nbformat": 4,
|
|
0 commit comments