Skip to content

Commit

Permalink
ch03 corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeldorman committed Sep 25, 2023
1 parent c33a61c commit 9e9f7e1
Showing 1 changed file with 17 additions and 9 deletions.
26 changes: 17 additions & 9 deletions 03-spatial-operations.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -833,13 +833,15 @@ First, let's take the array of `elev.tif` raster values, which we already read e
elev
```

Now, any element-wise array operation can be applied using **numpy** arithmetic or conditional operators and functions, comprising local raster operations in spatial analysis terminology. For example:
Now, any element-wise array operation can be applied using **numpy** arithmetic or conditional operators and functions, comprising local raster operations in spatial analysis terminology.
For example:

```{python}
elev + elev
```

Note that some functions and operators automatically change the data type to accomodate the resulting values, while other operators do not, potentially resulting in overflow (i.e., incorrect values for results beyond the data type range, such as `255` for `int8`). For example, `elev**2` (`elev` squared) results in overflow:
Note that some functions and operators automatically change the data type to accomodate the resulting values, while other operators do not, potentially resulting in overflow (i.e., incorrect values for results beyond the data type range, such as `255` for `int8`).
For example, `elev**2` (`elev` squared) results in overflow:

```{python}
elev**2
Expand Down Expand Up @@ -869,7 +871,8 @@ rasterio.plot.show(np.log(elev), cmap='Oranges');
rasterio.plot.show(elev > 5, cmap='Oranges');
```

Another good example of local operations is the classification of intervals of numeric values into groups such as grouping a digital elevation model into low (class 1), middle (class 2) and high elevations (class 3). Here, we assign the raster values in the ranges `0`--`12`, `12`--`24` and `24`--`36` are reclassified to take values `1`, `2` and `3`, respectively.
Another good example of local operations is the classification of intervals of numeric values into groups such as grouping a digital elevation model into low (class 1), middle (class 2) and high elevations (class 3).
Here, we assign the raster values in the ranges `0`--`12`, `12`--`24` and `24`--`36` are reclassified to take values `1`, `2` and `3`, respectively.

```{python}
recl = elev.copy()
Expand All @@ -892,7 +895,10 @@ rasterio.plot.show(elev, cmap='Oranges');
rasterio.plot.show(recl, cmap='Oranges');
```

The calculation of the [Normalized Difference Vegetation Index (NDVI)](https://en.wikipedia.org/wiki/Normalized_difference_vegetation_index) is a well-known local (pixel-by-pixel) raster operation. It returns a raster with values between `-1` and `1`; positive values indicate the presence of living plants (mostly > `0.2`). NDVI is calculated from red and near-infrared (NIR) bands of remotely sensed imagery, typically from satellite systems such as Landsat or Sentinel. Vegetation absorbs light heavily in the visible light spectrum, and especially in the red channel, while reflecting NIR light, explaining the NVDI formula (@eq-ndvi):
The calculation of the [Normalized Difference Vegetation Index (NDVI)](https://en.wikipedia.org/wiki/Normalized_difference_vegetation_index) is a well-known local (pixel-by-pixel) raster operation.
It returns a raster with values between `-1` and `1`; positive values indicate the presence of living plants (mostly > `0.2`).
NDVI is calculated from red and near-infrared (NIR) bands of remotely sensed imagery, typically from satellite systems such as Landsat or Sentinel.
Vegetation absorbs light heavily in the visible light spectrum, and especially in the red channel, while reflecting NIR light, explaining the NVDI formula (@eq-ndvi):

$$NDVI=\frac{NIR-Red} {NIR+Red}$${#eq-ndvi}

Expand All @@ -916,7 +922,7 @@ When plotting an RGB image using the `rasterio.plot.show` function, the function
* Values are in the range `[0,1]` for floats, or `[0,255]` for integers (otherwise clipped)
* The order of bands is RGB

To "prepare" the multi-band raster for `rasterio.plot.show`, we therefore reverse the order of the first three bands (to go from B-G-R-NIR to R-G-B), uisng the `[:3]` slice to select the first three bands and then the `[::-1]` slice to reverse the bands order, and divide by the maximum to set the maximum value at `1`:
To "prepare" the multi-band raster for `rasterio.plot.show`, we therefore reverse the order of the first three bands (to go from B-G-R-NIR to R-G-B), using the `[:3]` slice to select the first three bands and then the `[::-1]` slice to reverse the bands order, and divide by the maximum to set the maximum value at `1`:

```{python}
landsat_rgb = landsat[:3][::-1] / landsat.max()
Expand All @@ -939,10 +945,12 @@ rasterio.plot.show(ndvi, cmap='Greens');
### Focal operations {#sec-focal-operations}

While local functions operate on one cell, though possibly from multiple layers, focal operations take into account a central (focal) cell and its neighbors.
The neighborhood (also named kernel, filter or moving window) under consideration is typically of size 3-by-3 cells (that is the central cell and its eight surrounding neighbors), but can take on any other (not necessarily rectangular) shape as defined by the user.
A focal operation applies an aggregation function to all cells within the specified neighborhood, uses the corresponding output as the new value for the the central cell, and moves on to the next central cell (Figure ...).
The neighborhood (also named kernel, filter or moving window) under consideration is typically of $3 \times 3$ cells (that is the central cell and its eight surrounding neighbors), but can take on any other (not necessarily rectangular) shape as defined by the user.
A focal operation applies an aggregation function to all cells within the specified neighborhood, uses the corresponding output as the new value for the the central cell, and moves on to the next central cell (@fig-focal-filter).
Other names for this operation are spatial filtering and convolution (Burrough, McDonnell, and Lloyd 2015).

![Input raster (left) and resulting output raster (right) due to a focal operation---finding the minimum value in $3 \times 3$ moving windows.](https://r.geocompx.org/figures/04_focal_example.png){#fig-focal-filter}

In Python, the `scipy.ndimage` package has a comprehensive collection of [functions](https://docs.scipy.org/doc/scipy/reference/ndimage.html#filters) to perform filtering of `numpy` arrays, such as:

* `minimum_filter`
Expand All @@ -953,8 +961,8 @@ etc.

In this group of functions, we define the shape of the moving window with either one of:

* `size`a single number or tuple, implying a filter of those dimensions
* `footprint`a boolean array, representing both the window shape and the identity of elements being included
* `size`---a single number or tuple, implying a filter of those dimensions
* `footprint`---a boolean array, representing both the window shape and the identity of elements being included

In addition to specific built-in filters,

Expand Down

0 comments on commit 9e9f7e1

Please sign in to comment.