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:
tidyverse: This is primarily for various data
manipulation since the raster stack is just another data-frame.
terra: This is obviously for the raster
manipulation.
sf: This is for vector data manipulation. In our
case, a shapefile.
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:
- 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"
- 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=