Introduction

One of the simplest and common operations to be performed on raster objects is computation. This is used to extract specific details about the dataset by using the various aspects of the bands.

In this notebook, I will explore how to perform this computations, which is fairly is easy. I will be using the Normalized Difference Vegetation Index (NDVI). This is a basic index for getting the vegetative cover of anb area by using the surface reflectance of Near Infrared Band and Red Band that is band 5 and 4 respectively.

NDVI

The NDVI can be expressed in a mathematical formula that is :

\[ ndvi = (nir-red)/(nir+red) \]

Libraries

As established the three packages required are terra, tidyverse and sf.

library(terra)
library(tidyverse)
── Attaching core tidyverse packages ─────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.2     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.3     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     ── Conflicts ───────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ tidyr::extract() masks terra::extract()
✖ dplyr::filter()  masks stats::filter()
✖ dplyr::lag()     masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(sf)
Linking to GEOS 3.11.2, GDAL 3.6.2, PROJ 9.2.0; sf_use_s2() is TRUE
sceneDir <- "C:/Users/roywa/Data/LST/LC09_L2SP_168061_20230204_20230311_02_T1/NORMALISED/"
kiambu_stack <- rast(paste0(sceneDir, "KIAMBU_SUBSET_STACK.TIF"))

This is a plot to see how, if at all, the data has been loaded. Though it is unnecessary. I prefer the assurance that is the plot rendering without any skirmishes.

kiambu_stack$`B3` %>%
  plot()

NDVI function

This is a function that I will use to perform the NDVI calculations. I prefere this method since the function can be reused multiple times without error or failure.

calc_ndvi <- function(nir, red){
  ndvi <- (nir-red)/(nir+red)
  return(ndvi)
}

For instance: This here is the performance of the NDVI for the image subset. The function returns a raster with the values defined.

kiambu_ndvi <- lapp(c(kiambu_stack$B5, kiambu_stack$B4), fun=calc_ndvi)

In my case, I have used the data to plot the raster as well as a histogram to see distribution of the various data points.

par(mfrow=c(1,2))
kiambu_ndvi%>%
  plot(main="NDVI OF KIAMBU COUNTY")

kiambu_ndvi%>%
  hist(main = "NDVI values", xlab = "NDVI", ylab= "Frequency",
    col = "wheat", xlim = c(-0.5, 1),  breaks = 30, xaxt = "n"
    )%>%
  axis(side=1, at = seq(-0.6, 1, 0.2), labels = seq(-0.6, 1, 0.2))

This is a threshold cut. I am taking in the values above 0.4 only while the rest are interprated as Null values. This is benefitial if you want to show a specific phenomena that occurs above a certain range of the dataset.

kiambu_ndvi %>%
  clamp(0.4, values=FALSE)%>%
  plot()


Alternatively you can select a spefific range by changing the ranges into a matrix.

m <- c(-Inf, 0.25, NA,  0.25, 0.4, 1,  0.4, Inf, NA)
rcl <- matrix(m, ncol=3, byrow=TRUE)
land <- classify(kiambu_ndvi, rcl)
land %>%
  plot(col="brown")

Finally, the data can also be classified using a vector.

m <- c(-1,0.25, 0.3, 0.4, 0.6, 1)
vegc <- classify(kiambu_ndvi, m)
plot(vegc, col = c("red","brown","orange", "yellow", "green"), main = 'NDVI based thresholding')

Conclusion

This is a very small subset of the indices that are used with remotely sensed images. There are a number of indiced that are way more complicated than the NDVI. However, all the indices that you choose should have a theoretical backing so that you understand eh innner working of these indices.

LS0tDQp0aXRsZTogIkNyZWF0aW5nIGFuIE5EVkkgb2YgYSByYXN0ZXIiDQphdXRob3I6ICJSb3kgV2Fzd2EiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBJbnRyb2R1Y3Rpb24NCg0KT25lIG9mIHRoZSBzaW1wbGVzdCBhbmQgY29tbW9uIG9wZXJhdGlvbnMgdG8gYmUgcGVyZm9ybWVkIG9uIHJhc3RlciBvYmplY3RzIGlzIGNvbXB1dGF0aW9uLiBUaGlzIGlzIHVzZWQgdG8gZXh0cmFjdCBzcGVjaWZpYyBkZXRhaWxzIGFib3V0IHRoZSBkYXRhc2V0IGJ5IHVzaW5nIHRoZSB2YXJpb3VzIGFzcGVjdHMgb2YgdGhlIGJhbmRzLg0KDQpJbiB0aGlzIG5vdGVib29rLCBJIHdpbGwgZXhwbG9yZSBob3cgdG8gcGVyZm9ybSB0aGlzIGNvbXB1dGF0aW9ucywgd2hpY2ggaXMgZmFpcmx5IGlzIGVhc3kuIEkgd2lsbCBiZSB1c2luZyB0aGUgTm9ybWFsaXplZCBEaWZmZXJlbmNlIFZlZ2V0YXRpb24gSW5kZXggKE5EVkkpLiBUaGlzIGlzIGEgYmFzaWMgaW5kZXggZm9yIGdldHRpbmcgdGhlIHZlZ2V0YXRpdmUgY292ZXIgb2YgYW5iIGFyZWEgYnkgdXNpbmcgdGhlIHN1cmZhY2UgcmVmbGVjdGFuY2Ugb2YgTmVhciBJbmZyYXJlZCBCYW5kIGFuZCBSZWQgQmFuZCB0aGF0IGlzIGJhbmQgNSBhbmQgNCByZXNwZWN0aXZlbHkuDQoNCiMjIE5EVkkNCg0KVGhlIE5EVkkgY2FuIGJlIGV4cHJlc3NlZCBpbiBhIG1hdGhlbWF0aWNhbCBmb3JtdWxhIHRoYXQgaXMgOg0KDQokJA0KbmR2aSA9IChuaXItcmVkKS8obmlyK3JlZCkNCiQkDQoNCiMjIExpYnJhcmllcw0KDQpBcyBlc3RhYmxpc2hlZCB0aGUgdGhyZWUgcGFja2FnZXMgcmVxdWlyZWQgYXJlIGB0ZXJyYWAsIGB0aWR5dmVyc2VgIGFuZCBgc2ZgLg0KDQpgYGB7ciBsaWJyYXJpZXN9DQpsaWJyYXJ5KHRlcnJhKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNmKQ0KDQpgYGANCg0KYGBge3IgZGF0YX0NCnNjZW5lRGlyIDwtICJDOi9Vc2Vycy9yb3l3YS9EYXRhL0xTVC9MQzA5X0wyU1BfMTY4MDYxXzIwMjMwMjA0XzIwMjMwMzExXzAyX1QxL05PUk1BTElTRUQvIg0Ka2lhbWJ1X3N0YWNrIDwtIHJhc3QocGFzdGUwKHNjZW5lRGlyLCAiS0lBTUJVX1NVQlNFVF9TVEFDSy5USUYiKSkNCmBgYA0KDQpUaGlzIGlzIGEgcGxvdCB0byBzZWUgaG93LCBpZiBhdCBhbGwsIHRoZSBkYXRhIGhhcyBiZWVuIGxvYWRlZC4gVGhvdWdoIGl0IGlzIHVubmVjZXNzYXJ5LiBJIHByZWZlciB0aGUgYXNzdXJhbmNlIHRoYXQgaXMgdGhlIHBsb3QgcmVuZGVyaW5nIHdpdGhvdXQgYW55IHNraXJtaXNoZXMuDQoNCmBgYHtyIHJhbmRvbSBwbG90fQ0Ka2lhbWJ1X3N0YWNrJGBCM2AgJT4lDQogIHBsb3QoKQ0KYGBgDQoNCiMjIE5EVkkgZnVuY3Rpb24NCg0KVGhpcyBpcyBhIGZ1bmN0aW9uIHRoYXQgSSB3aWxsIHVzZSB0byBwZXJmb3JtIHRoZSBORFZJIGNhbGN1bGF0aW9ucy4gSSBwcmVmZXJlIHRoaXMgbWV0aG9kIHNpbmNlIHRoZSBmdW5jdGlvbiBjYW4gYmUgcmV1c2VkIG11bHRpcGxlIHRpbWVzIHdpdGhvdXQgZXJyb3Igb3IgZmFpbHVyZS4NCg0KYGBge3J9DQpjYWxjX25kdmkgPC0gZnVuY3Rpb24obmlyLCByZWQpew0KICBuZHZpIDwtIChuaXItcmVkKS8obmlyK3JlZCkNCiAgcmV0dXJuKG5kdmkpDQp9DQpgYGANCg0KRm9yIGluc3RhbmNlOiBUaGlzIGhlcmUgaXMgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBORFZJIGZvciB0aGUgaW1hZ2Ugc3Vic2V0LiBUaGUgZnVuY3Rpb24gcmV0dXJucyBhIHJhc3RlciB3aXRoIHRoZSB2YWx1ZXMgZGVmaW5lZC4NCg0KYGBge3J9DQpraWFtYnVfbmR2aSA8LSBsYXBwKGMoa2lhbWJ1X3N0YWNrJEI1LCBraWFtYnVfc3RhY2skQjQpLCBmdW49Y2FsY19uZHZpKQ0KYGBgDQoNCkluIG15IGNhc2UsIEkgaGF2ZSB1c2VkIHRoZSBkYXRhIHRvIHBsb3QgdGhlIHJhc3RlciBhcyB3ZWxsIGFzIGEgaGlzdG9ncmFtIHRvIHNlZSBkaXN0cmlidXRpb24gb2YgdGhlIHZhcmlvdXMgZGF0YSBwb2ludHMuDQoNCmBgYHtyfQ0KcGFyKG1mcm93PWMoMSwyKSkNCmtpYW1idV9uZHZpJT4lDQogIHBsb3QobWFpbj0iTkRWSSBPRiBLSUFNQlUgQ09VTlRZIikNCg0Ka2lhbWJ1X25kdmklPiUNCiAgaGlzdChtYWluID0gIk5EVkkgdmFsdWVzIiwgeGxhYiA9ICJORFZJIiwgeWxhYj0gIkZyZXF1ZW5jeSIsDQogICAgY29sID0gIndoZWF0IiwgeGxpbSA9IGMoLTAuNSwgMSksICBicmVha3MgPSAzMCwgeGF4dCA9ICJuIg0KICAgICklPiUNCiAgYXhpcyhzaWRlPTEsIGF0ID0gc2VxKC0wLjYsIDEsIDAuMiksIGxhYmVscyA9IHNlcSgtMC42LCAxLCAwLjIpKQ0KYGBgDQoNClRoaXMgaXMgYSB0aHJlc2hvbGQgY3V0LiBJIGFtIHRha2luZyBpbiB0aGUgdmFsdWVzIGFib3ZlIDAuNCBvbmx5IHdoaWxlIHRoZSByZXN0IGFyZSBpbnRlcnByYXRlZCBhcyBOdWxsIHZhbHVlcy4gVGhpcyBpcyBiZW5lZml0aWFsIGlmIHlvdSB3YW50IHRvIHNob3cgYSBzcGVjaWZpYyBwaGVub21lbmEgdGhhdCBvY2N1cnMgYWJvdmUgYSBjZXJ0YWluIHJhbmdlIG9mIHRoZSBkYXRhc2V0Lg0KDQpgYGB7cn0NCmtpYW1idV9uZHZpICU+JQ0KICBjbGFtcCgwLjQsIHZhbHVlcz1GQUxTRSklPiUNCiAgcGxvdCgpDQpgYGANCg0KXA0KQWx0ZXJuYXRpdmVseSB5b3UgY2FuIHNlbGVjdCBhIHNwZWZpZmljIHJhbmdlIGJ5IGNoYW5naW5nIHRoZSByYW5nZXMgaW50byBhIG1hdHJpeC4NCg0KYGBge3J9DQptIDwtIGMoLUluZiwgMC4yNSwgTkEsICAwLjI1LCAwLjQsIDEsICAwLjQsIEluZiwgTkEpDQpyY2wgPC0gbWF0cml4KG0sIG5jb2w9MywgYnlyb3c9VFJVRSkNCmxhbmQgPC0gY2xhc3NpZnkoa2lhbWJ1X25kdmksIHJjbCkNCmxhbmQgJT4lDQogIHBsb3QoY29sPSJicm93biIpDQpgYGANCg0KRmluYWxseSwgdGhlIGRhdGEgY2FuIGFsc28gYmUgY2xhc3NpZmllZCB1c2luZyBhIHZlY3Rvci4NCg0KYGBge3J9DQptIDwtIGMoLTEsMC4yNSwgMC4zLCAwLjQsIDAuNiwgMSkNCnZlZ2MgPC0gY2xhc3NpZnkoa2lhbWJ1X25kdmksIG0pDQpwbG90KHZlZ2MsIGNvbCA9IGMoInJlZCIsImJyb3duIiwib3JhbmdlIiwgInllbGxvdyIsICJncmVlbiIpLCBtYWluID0gJ05EVkkgYmFzZWQgdGhyZXNob2xkaW5nJykNCmBgYA0KDQojIyBDb25jbHVzaW9uDQoNClRoaXMgaXMgYSB2ZXJ5IHNtYWxsIHN1YnNldCBvZiB0aGUgaW5kaWNlcyB0aGF0IGFyZSB1c2VkIHdpdGggcmVtb3RlbHkgc2Vuc2VkIGltYWdlcy4gVGhlcmUgYXJlIGEgbnVtYmVyIG9mIGluZGljZWQgdGhhdCBhcmUgd2F5IG1vcmUgY29tcGxpY2F0ZWQgdGhhbiB0aGUgTkRWSS4gSG93ZXZlciwgYWxsIHRoZSBpbmRpY2VzIHRoYXQgeW91IGNob29zZSBzaG91bGQgaGF2ZSBhIHRoZW9yZXRpY2FsIGJhY2tpbmcgc28gdGhhdCB5b3UgdW5kZXJzdGFuZCBlaCBpbm5uZXIgd29ya2luZyBvZiB0aGVzZSBpbmRpY2VzLg0K