Introduction

This is a brief notebook to use a stacked Landsat 9 image to extract an ROI. In my case, I will be using the county of Kiambu in Kenya. This is because the county is perfectly inside one scene, this offers ease in extracting the ROI. I will come up with another notebook to detail how to extract the ROI of an area where the scenes overlap.

Importing the files

I will be using the previously stacked image to get my area extract LC09_L2SP_STACK_1_7.TIF. I will utilise three libraries:

library(tidyverse)
library(plotly)
library(terra)
library(sf)
imgDir = "C:/Users/roywa/Data/LST/LC09_L2SP_168061_20230119_20230313_02_T1/"
imgName = "LC09_L2SP_STACK_1_7.TIF"
imgPath = paste0(imgDir, imgName)

kiambuFilePath = "C:/Users/roywa/Data/SHP/Kiambu/"
imgData <- rast(imgPath)
kiambu <- st_read(kiambuFilePath, drivers="ESRI Shapefile")
options:        ESRI Shapefile 
Reading layer `Kiambu' from data source `C:\Users\roywa\Data\SHP\Kiambu' using driver `ESRI Shapefile'
Simple feature collection with 1 feature and 12 fields
Geometry type: POLYGON
Dimension:     XY
Bounding box:  xmin: 36.49081 ymin: -1.312168 xmax: 37.3626 ymax: -0.7566282
Geodetic CRS:  WGS 84
print("IMAGE SUMMARY")
[1] "IMAGE SUMMARY"
print(imgData)
class       : SpatRaster 
dimensions  : 7731, 7591, 7  (nrow, ncol, nlyr)
resolution  : 30, 30  (x, y)
extent      : 175185, 402915, -276315, -44385  (xmin, xmax, ymin, ymax)
coord. ref. : WGS 84 / UTM zone 37N (EPSG:32637) 
source      : LC09_L2SP_STACK_1_7.TIF 
names       : BAND 1, BAND 2, BAND 3, BAND 4, BAND 5, BAND 6, ... 
min values  :      1,      5,    130,     74,   6152,   7554, ... 
max values  :  42745,  42834,  41997,  42694,  44407,  52291, ... 

Observing the data

Looking at the data we notice a few things:

  1. The Image has bands so that means that it is a stacked image. The one we created in the previous notebook. Additionally we can check this with the names() function
imgData %>%
  names()
[1] "BAND 1" "BAND 2" "BAND 3" "BAND 4" "BAND 5" "BAND 6" "BAND 7"
  1. The two datasets are of different CRS; this means that we cannot perform any operation that involves the two together
crs(kiambu, proj=TRUE)
[1] "+proj=longlat +datum=WGS84 +no_defs"
crs(imgData, proj=TRUE)
[1] "+proj=utm +zone=37 +datum=WGS84 +units=m +no_defs"

Re-projection

The natural next step is to re-project these datasets so that they conform to each other and therefore operations can be performed on them. In this case of the data, I would rather re-project the vector dataset than the image. The image has 7 layers that would require warping and the image takes a whooping 700MB on disk.

kiambu_utm <- kiambu %>%
  st_transform(crs(imgData))
par(mfrow=c(1,2))
vect(kiambu)%>%
  plot(main="Kiambu latlong", col="red")
vect(kiambu_utm) %>%
  plot(main="Kiambu UTM", col="blue")

In the plot above we can see the red plot being the WGS84 plot with latlong graduation while the blue one is the one that we aim to use since its in the same projection

crs(kiambu_utm) == crs(imgData)
[1] TRUE

For the image that I want to mask:

plotRGB(c(
  imgData$`BAND 4`,
  imgData$`BAND 3`,
  imgData$`BAND 2`
))

Masking

So now I have an imgData that for the sake of understanding I will use the 4th band for visualizing what is happening.

plot(imgData$`BAND 4`)
lines(vect(kiambu_utm))

This is proof that these two objects are in fact in the same CRS and that operations can be performed on both of them.

kiambu_subset_name = "KIAMBU_LC09_L2SP_STACK_1_7.TIF"
kiambu_crop <- terra::crop(imgData, kiambu_utm)
kiambu_mask <- terra::mask(kiambu_crop, kiambu_utm, 
                           inverse=FALSE,
                           overwrite=TRUE, 
                           filename=paste0(imgDir,kiambu_subset_name))
kiambu_mask %>%
  plot()

plotRGB(c(
  kiambu_mask$`BAND 4`,
  kiambu_mask$`BAND 3`,
  kiambu_mask$`BAND 2`
))

And that is how you get a mask of a stacked image. The same method can be used for an individual image, however, I don’t fancy that method due to the loops that you have to implement to get the job done.

LS0tDQp0aXRsZTogIk1hc2tpbmcgTGFuZHNhdCA5IGltYWdlcyB1c2luZyBhIHNoYXBlZmlsZSBvZiBhbiBST0kiDQphdXRob3I6ICJSb3kgV2Fzd2EiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQojIyBJbnRyb2R1Y3Rpb24NCg0KVGhpcyBpcyBhIGJyaWVmIG5vdGVib29rIHRvIHVzZSBhIHN0YWNrZWQgTGFuZHNhdCA5IGltYWdlIHRvIGV4dHJhY3QgYW4gUk9JLiBJbiBteSBjYXNlLCBJIHdpbGwgYmUgdXNpbmcgdGhlIGNvdW50eSBvZiBLaWFtYnUgaW4gS2VueWEuIFRoaXMgaXMgYmVjYXVzZSB0aGUgY291bnR5IGlzIHBlcmZlY3RseSBpbnNpZGUgb25lIHNjZW5lLCB0aGlzIG9mZmVycyBlYXNlIGluIGV4dHJhY3RpbmcgdGhlIFJPSS4gSSB3aWxsIGNvbWUgdXAgd2l0aCBhbm90aGVyIG5vdGVib29rIHRvIGRldGFpbCBob3cgdG8gZXh0cmFjdCB0aGUgUk9JIG9mIGFuIGFyZWEgd2hlcmUgdGhlIHNjZW5lcyBvdmVybGFwLg0KDQojIyBJbXBvcnRpbmcgdGhlIGZpbGVzDQoNCkkgd2lsbCBiZSB1c2luZyB0aGUgcHJldmlvdXNseSBzdGFja2VkIGltYWdlIHRvIGdldCBteSBhcmVhIGV4dHJhY3QgYExDMDlfTDJTUF9TVEFDS18xXzcuVElGYC4gSSB3aWxsIHV0aWxpc2UgdGhyZWUgbGlicmFyaWVzOg0KDQotICAgYHRpZHl2ZXJzZWA6IFRoaXMgaXMgcHJpbWFyaWx5IGZvciB2YXJpb3VzIGRhdGEgbWFuaXB1bGF0aW9uIHNpbmNlIHRoZSByYXN0ZXIgc3RhY2sgaXMganVzdCBhbm90aGVyIGRhdGEtZnJhbWUuDQoNCi0gICBgdGVycmFgOiBUaGlzIGlzIG9idmlvdXNseSBmb3IgdGhlIHJhc3RlciBtYW5pcHVsYXRpb24uDQoNCi0gICBgc2ZgOiBUaGlzIGlzIGZvciB2ZWN0b3IgZGF0YSBtYW5pcHVsYXRpb24uIEluIG91ciBjYXNlLCBhIHNoYXBlZmlsZS4NCg0KYGBge3IgbGlicmFyaWVzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeSh0ZXJyYSkNCmxpYnJhcnkoc2YpDQpgYGANCg0KYGBge3IgZmlsZXN9DQppbWdEaXIgPSAiQzovVXNlcnMvcm95d2EvRGF0YS9MU1QvTEMwOV9MMlNQXzE2ODA2MV8yMDIzMDExOV8yMDIzMDMxM18wMl9UMS8iDQppbWdOYW1lID0gIkxDMDlfTDJTUF9TVEFDS18xXzcuVElGIg0KaW1nUGF0aCA9IHBhc3RlMChpbWdEaXIsIGltZ05hbWUpDQoNCmtpYW1idUZpbGVQYXRoID0gIkM6L1VzZXJzL3JveXdhL0RhdGEvU0hQL0tpYW1idS8iDQpgYGANCg0KYGBge3IgZGF0YWxvYWR9DQppbWdEYXRhIDwtIHJhc3QoaW1nUGF0aCkNCmtpYW1idSA8LSBzdF9yZWFkKGtpYW1idUZpbGVQYXRoLCBkcml2ZXJzPSJFU1JJIFNoYXBlZmlsZSIpDQpwcmludCgiSU1BR0UgU1VNTUFSWSIpDQpwcmludChpbWdEYXRhKQ0KYGBgDQoNCiMjIE9ic2VydmluZyB0aGUgZGF0YQ0KDQpMb29raW5nIGF0IHRoZSBkYXRhIHdlIG5vdGljZSBhIGZldyB0aGluZ3M6DQoNCjEuICBUaGUgSW1hZ2UgaGFzIGJhbmRzIHNvIHRoYXQgbWVhbnMgdGhhdCBpdCBpcyBhIHN0YWNrZWQgaW1hZ2UuIFRoZSBvbmUgd2UgY3JlYXRlZCBpbiB0aGUgcHJldmlvdXMgbm90ZWJvb2suIEFkZGl0aW9uYWxseSB3ZSBjYW4gY2hlY2sgdGhpcyB3aXRoIHRoZSBgbmFtZXMoKWAgZnVuY3Rpb24NCg0KYGBge3J9DQppbWdEYXRhICU+JQ0KICBuYW1lcygpDQpgYGANCg0KMi4gIFRoZSB0d28gZGF0YXNldHMgYXJlIG9mIGRpZmZlcmVudCBDUlM7IHRoaXMgbWVhbnMgdGhhdCB3ZSBjYW5ub3QgcGVyZm9ybSBhbnkgb3BlcmF0aW9uIHRoYXQgaW52b2x2ZXMgdGhlIHR3byB0b2dldGhlcg0KDQpgYGB7cn0NCmNycyhraWFtYnUsIHByb2o9VFJVRSkNCmNycyhpbWdEYXRhLCBwcm9qPVRSVUUpDQpgYGANCg0KIyMgUmUtcHJvamVjdGlvbg0KDQpUaGUgbmF0dXJhbCBuZXh0IHN0ZXAgaXMgdG8gcmUtcHJvamVjdCB0aGVzZSBkYXRhc2V0cyBzbyB0aGF0IHRoZXkgY29uZm9ybSB0byBlYWNoIG90aGVyIGFuZCB0aGVyZWZvcmUgb3BlcmF0aW9ucyBjYW4gYmUgcGVyZm9ybWVkIG9uIHRoZW0uIEluIHRoaXMgY2FzZSBvZiB0aGUgZGF0YSwgSSB3b3VsZCByYXRoZXIgcmUtcHJvamVjdCB0aGUgdmVjdG9yIGRhdGFzZXQgdGhhbiB0aGUgaW1hZ2UuIFRoZSBpbWFnZSBoYXMgNyBsYXllcnMgdGhhdCB3b3VsZCByZXF1aXJlIHdhcnBpbmcgYW5kIHRoZSBpbWFnZSB0YWtlcyBhIHdob29waW5nIDcwME1CIG9uIGRpc2suDQoNCmBgYHtyfQ0Ka2lhbWJ1X3V0bSA8LSBraWFtYnUgJT4lDQogIHN0X3RyYW5zZm9ybShjcnMoaW1nRGF0YSkpDQpgYGANCg0KYGBge3J9DQpwYXIobWZyb3c9YygxLDIpKQ0KdmVjdChraWFtYnUpJT4lDQogIHBsb3QobWFpbj0iS2lhbWJ1IGxhdGxvbmciLCBjb2w9InJlZCIpDQp2ZWN0KGtpYW1idV91dG0pICU+JQ0KICBwbG90KG1haW49IktpYW1idSBVVE0iLCBjb2w9ImJsdWUiKQ0KYGBgDQoNCkluIHRoZSBwbG90IGFib3ZlIHdlIGNhbiBzZWUgdGhlIHJlZCBwbG90IGJlaW5nIHRoZSBXR1M4NCBwbG90IHdpdGggbGF0bG9uZyBncmFkdWF0aW9uIHdoaWxlIHRoZSBibHVlIG9uZSBpcyB0aGUgb25lIHRoYXQgd2UgYWltIHRvIHVzZSBzaW5jZSBpdHMgaW4gdGhlIHNhbWUgcHJvamVjdGlvbg0KDQpgYGB7cn0NCmNycyhraWFtYnVfdXRtKSA9PSBjcnMoaW1nRGF0YSkNCmBgYA0KDQpGb3IgdGhlIGltYWdlIHRoYXQgSSB3YW50IHRvIG1hc2s6DQoNCmBgYHtyfQ0KcGxvdFJHQihjKA0KICBpbWdEYXRhJGBCQU5EIDRgLA0KICBpbWdEYXRhJGBCQU5EIDNgLA0KICBpbWdEYXRhJGBCQU5EIDJgDQopKQ0KYGBgDQoNCiMjIE1hc2tpbmcNCg0KU28gbm93IEkgaGF2ZSBhbiBgaW1nRGF0YWAgdGhhdCBmb3IgdGhlIHNha2Ugb2YgdW5kZXJzdGFuZGluZyBJIHdpbGwgdXNlIHRoZSA0dGggYmFuZCBmb3IgdmlzdWFsaXppbmcgd2hhdCBpcyBoYXBwZW5pbmcuDQoNCmBgYHtyfQ0KcGxvdChpbWdEYXRhJGBCQU5EIDRgKQ0KbGluZXModmVjdChraWFtYnVfdXRtKSkNCmBgYA0KDQpUaGlzIGlzIHByb29mIHRoYXQgdGhlc2UgdHdvIG9iamVjdHMgYXJlIGluIGZhY3QgaW4gdGhlIHNhbWUgQ1JTIGFuZCB0aGF0IG9wZXJhdGlvbnMgY2FuIGJlIHBlcmZvcm1lZCBvbiBib3RoIG9mIHRoZW0uDQoNCmBgYHtyfQ0Ka2lhbWJ1X3N1YnNldF9uYW1lID0gIktJQU1CVV9MQzA5X0wyU1BfU1RBQ0tfMV83LlRJRiINCmtpYW1idV9jcm9wIDwtIHRlcnJhOjpjcm9wKGltZ0RhdGEsIGtpYW1idV91dG0pDQpraWFtYnVfbWFzayA8LSB0ZXJyYTo6bWFzayhraWFtYnVfY3JvcCwga2lhbWJ1X3V0bSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBpbnZlcnNlPUZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcndyaXRlPVRSVUUsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWU9cGFzdGUwKGltZ0RpcixraWFtYnVfc3Vic2V0X25hbWUpKQ0KYGBgDQoNCmBgYHtyfQ0Ka2lhbWJ1X21hc2sgJT4lDQogIHBsb3QoKQ0KYGBgDQoNCmBgYHtyfQ0KcGxvdFJHQihjKA0KICBraWFtYnVfbWFzayRgQkFORCA0YCwNCiAga2lhbWJ1X21hc2skYEJBTkQgM2AsDQogIGtpYW1idV9tYXNrJGBCQU5EIDJgDQopKQ0KYGBgDQoNCkFuZCB0aGF0IGlzIGhvdyB5b3UgZ2V0IGEgbWFzayBvZiBhIHN0YWNrZWQgaW1hZ2UuIFRoZSBzYW1lIG1ldGhvZCBjYW4gYmUgdXNlZCBmb3IgYW4gaW5kaXZpZHVhbCBpbWFnZSwgaG93ZXZlciwgSSBkb24ndCBmYW5jeSB0aGF0IG1ldGhvZCBkdWUgdG8gdGhlIGxvb3BzIHRoYXQgeW91IGhhdmUgdG8gaW1wbGVtZW50IHRvIGdldCB0aGUgam9iIGRvbmUuDQo=