Chapter 11 Crown-level Vegetation Indicies
Vegetation indices (VIs) are important tools for near-real time monitoring and function as proxies for health, productivity, structural changes, and stress.
Below we describe a few commonly used VIs that will be calculated in this workflow:
Normalized Difference Vegetation Index (NDVI) is one of the oldest vegetation indices established in vegetation monitoring and is used as a metric of greenness. However, due to saturation of the chlorophyll absorption peak around 660-680nm at moderately low chlorophyll levels, NDVI is often not able to tease out small differences between healthy plants (Sims & Gamon, 2002). To solve this issue, the red reflectance band can be replaced with a red edge reflectance band creating the normalized difference red edge index mentioned below.
Normalized Difference Red Edge index (NDRE) normalizes a reflectance band in the red edge to a reflectance band in the near-infrared region to estimate chlorophyll content. This index is a derivative of NDVI that is sensitive to shifts in chlorophyll content at high concentrations (Clevers & Gitelson, 2013; Evangelides & Nobajas, 2020).
Chlorophyll Carotenoid Index (CCI) is a proxy for the ratio of chlorophylls to carotenoids in pigment pools. It is often used as a metric for tracking the onset of the growing season and photosynthetic activity (Gamon et al., 2016).
Photochemical Reflectance Index (PRI) can be used as a proxy for xanthophyll pigment epoxidation or changes in bulk seasonal pigment pool ratios depending on the timescale of analysis. Over a scale of milliseconds to minutes PRI can isolate the photoprotective conversion of violaxanthin into antheraxanthin and zeaxanthin within the xanthophyll cycle by normalizing the 531nm reflectance band to the 560nm reference reflectance band. However, on the seasonal scale the 560nm reflectance band no longer acts as a reference for isolating changes in xanthophyll pigments since it changes with bulk pigment shifts. Hence, seasonal PRI measurements are instead used as another proxy for the ratio of carotenoid to chlorophyll pigments and are used to show changes in photosynthetic activity (Wong et al., 2020).
Red Edge (RE) slope captures changes in chlorophyl content and structural health. Steep RE slopes generally indicate healthy vegetation while more gradual slopes often indicate stressed vegetation. This is due to the base of the RE slope sitting around a main chlorophyll absorption peak and the end of the RE slope sitting near the near-infrared (NIR) range. Hence, the more chlorophyll the lower the reflectance around the base of the RE slope and the greater the reflectance in the NIR, often attributed to healthy vegetative material, the steeper the overall slope of the RE (Sims and Gamon, 2002, Clevers and Gitelson)
Green Chromatic Cordinate (GCC) is a measure of green reflectance relative to the total reflectance in the visible light portion on the electromagnetic spectrum. It is a metric of greeness that is often used as a proxy for vegetation health (Reid et al., 2016).
11.1 VI Workflow
Below are code chunks that take the delineated crowns and multispectral orthomosaics and output a .rds file containing several popular vegetation indices at the crown-level. In this script we demonstrate how to calculate both mean and median values of vegetation indices per crown.
We begin by loading the necessary packages:Click to show the code
Next, we read in the multispectral orthomosaic and shadow mask. The shadow mask will work to remove shadowed pixels so they do not skew the values for the vegetation indices. See the section on shadow masks for a detailed workflow.
Click to show the code
# Load in multispectral orthomosaic
ms_ortho = rast(list.files(paste0(dir, "metashape\\3_MS_ORTHO\\"), pattern = ".*MS_Calibrated.*_bestPanel.tif$", full.names = TRUE)) #path to multispectral ortho
# Reading in the NIR shadow mask
shadow_mask = rast(list.files(paste0(dir, Nir_shadow_folder,"\\"), pattern = ".*_NIR_shadow.*_thresh.*_mask2.tif$", full.names = TRUE))# NIR shadow mask
# Below selects the root name of the multispectral ortho ie: "Name_of_multispectral_ortho" that will be used to name the multispectral shadow masked orthos created in the following steps
ms_ortho_name_root <- substr(names(ms_ortho)[1], 1, nchar(names(ms_ortho)[1]) - 2)
#names(ms_ortho)[1] grabs the name for band 1 of the ms_ortho: ie: "Name_of_multispectral_ortho_1", so that the substr function can selection the rootname as done above
To speed up processing, we mask the shadow mask to only contain areas inside delineated crowns.
The shadow mask is a raster containing values 1 (shadowed pixel) and NA (not shadowed pixel). The mask function below identifies pixels in the multispectral orthomosaic that align with shadowed pixels in the shadow mask and changes their value to NA.
Click to show the code
# Mask shadow mask to delineated crowns:
shadow_mask <- terra::mask(shadow_mask, pols)
# Mask the multispectral ortho using the shadow mask
ms_mask <- terra::mask(ms_ortho, shadow_mask, maskvalues = 1, updatevalue = NA)
#writing out the shadow masked multispectral ortho
terra::writeRaster(ms_mask, paste0(dir, Nir_shadow_folder,"\\",ms_ortho_name_root,"_NirShadow_masked.tif"),
overwrite = TRUE)
The shadow masked multispectral orthomosaic is then masked to the delineated crowns polygon to speed raster calculations in the next step.
Click to show the code
Here we calculate several vegetation indices using the multispectral orthomosaic from above with shadowed pixels and non-crown pixels removed.
Click to show the code
# List of band reflectances (R444 - R842) and index values that will be calculated per tree crown
rast_list = list(
# reflectance values
R444 = ms_mask[[1]],
R475 = ms_mask[[2]],
R531 = ms_mask[[3]],
R560 = ms_mask[[4]],
R650 = ms_mask[[5]],
R668 = ms_mask[[6]],
R705 = ms_mask[[7]],
R717 = ms_mask[[8]],
R740 = ms_mask[[9]],
R842 = ms_mask[[10]],
# Near-infrared greenness
mDatt = (ms_mask[[10]] - ms_mask[[8]]) / (ms_mask[[10]] - ms_mask[[6]]),
NDVI = (ms_mask[[10]] - ms_mask[[6]]) / (ms_mask[[10]] + ms_mask[[6]]),
# Chlorophyll
NDRE1 = (ms_mask[[10]] - ms_mask[[7]]) / (ms_mask[[10]] + ms_mask[[7]]),
NDRE2 = (ms_mask[[10]] - ms_mask[[8]]) / (ms_mask[[10]] + ms_mask[[8]]),
NDRE3 = (ms_mask[[10]] - ms_mask[[9]]) / (ms_mask[[10]] + ms_mask[[9]]),
EVI = (2.5 * (ms_mask[[10]] - ms_mask[[6]])) / (ms_mask[[10]] + (6 * ms_mask[[6]]) - ( 7.5 * ms_mask[[1]] + 1)),
GCC = (ms_mask[[4]]+ ms_mask[[3]]) / (ms_mask[[1]] + ms_mask[[2]] + ms_mask[[3]]+ms_mask[[4]] + ms_mask[[5]] + ms_mask[[6]]),
# Carotenoids, waxes
ARI = (1 / ms_mask[[4]]) - (1 / ms_mask[[7]]),
EWI9 = (ms_mask[[6]] - ms_mask[[8]]) / (ms_mask[[6]] + ms_mask[[8]]),
# Carotenoids
PRI = (ms_mask[[3]] - ms_mask[[4]]) / (ms_mask[[3]] + ms_mask[[4]]),
CCI = (ms_mask[[3]] - ms_mask[[5]]) / (ms_mask[[3]] + ms_mask[[5]]),
# Red edge
RE_upper = (ms_mask[[9]] - ms_mask[[8]]) / 23,
RE_lower = (ms_mask[[8]] - ms_mask[[7]]) / 12,
RE_total = (ms_mask[[9]] - ms_mask[[7]]) / 35
)
rast_all = rast(rast_list)
Below is an example of the resolution of the calculated vegetation indices. The image shows the chlorophyll carotenoid index (CCI) of a single crown across four summer time points. Greener pixels represent a higher ratio of chlorophylls to carotenoids. As you can see, the proportion of the crown with high CCI values increases from the May to July acquisitions, when productivity is likely at its highest, and decreases during the august acquisition suggesting lower productivity, likely due to end of summer drought conditions.
Lastly, we use the exact_extract function to calculate crown-level statistics per vegetation index raster created above. Below we show an example of taking the mean and median crown values per index as well as count the number of pixels that were used for the index calculation. We do this as a data quality check so we can remove crowns that had very few pixels involved in their index calculation.
Note: the append_cols parameter should be set to a list of column names that exist in pols (the shapefile of delineated crowns) that you would like to be appended to the dataframe containing vegetation indcies per tree crown. As you can see below we have attached many columns we found useful, however the only column necessary to append is a column in pols that represents a unique ID per tree crown.
Click to show the code
# Calculating Mean Index values per crown
df_spectral_mean = exact_extract(rast_all, pols, fun = "mean", append_cols = c("treeID","Edited","tag__","rep","blk","fam","fem"))
# Calculating the number of non-masked pixels used for index calculation
df_count = exact_extract(ms_mask[[1]], pols, fun = "count", progress = TRUE, append_cols = c("treeID","Edited","tag__","rep","blk","fam","fem"))
# Joining the mean index values df and the count values df
df_spectral_mean_count <- merge(df_spectral_mean,df_count, by = c("treeID","Edited","tag__","rep","blk","fam","fem"))
# Saving out mean crown values + non masked pixel count to an rds file
saveRDS(df_spectral_mean_count, paste0(dir_D,"\\",updated_metrics_folder,"\\", date_list[x], "_NIRshadowMask_MeanCrownSpectralIndices.rds"))
# Calculating Median Index values per crown
df_spectral_median = exact_extract(rast_all, pols, fun = "median", append_cols = c("treeID","Edited","tag__","rep","blk","fam","fem"))
df_spectral_median_count <- merge(df_spectral_median,df_count, by = c("treeID","Edited","tag__","rep","blk","fam","fem"))
# Saving out median crown values + non masked pixel count to an rds file
saveRDS(df_spectral_median_count, paste0(dir_D,"\\",updated_metrics_folder,"\\", date_list[x], "_NIRshadowMask_MedianCrownSpectralIndices.rds"))
References:
Clevers, J. G. P. W., & Gitelson, A. A. (2013). Remote estimation of crop and grass chlorophyll and nitrogen content using red-edge bands on Sentinel-2 and -3. International Journal of Applied Earth Observation and Geoinformation, 23(1), 344–351. https://doi.org/10.1016/J.JAG.2012.10.008
Evangelides, C., & Nobajas, A. (2020). Red-Edge Normalised Difference Vegetation Index (NDVI705) from Sentinel-2 imagery to assess post-fire regeneration. Remote Sensing Applications: Society and Environment, 17, 100283. https://doi.org/10.1016/J.RSASE.2019.100283
Gamon, J. A., Huemmrich, K. F., Wong, C. Y. S., Ensminger, I., Garrity, S., Hollinger, D. Y., Noormets, A., & Peñuelask, J. (2016). A remotely sensed pigment index reveals photosynthetic phenology in evergreen conifers. Proceedings of the National Academy of Sciences of the United States of America, 113(46), 13087–13092. https://doi.org/10.1073/pnas.1606162113
Reid, A. M., Chapman, W. K., Prescott, C. E., & Nijland, W. (2016). Using excess greenness and green chromatic coordinate colour indices from aerial images to assess lodgepole pine vigour, mortality and disease occurrence. Forest Ecology and Management, 374, 146–153. https://doi.org/10.1016/J.FORECO.2016.05.006
Sims, D. A., & Gamon, J. A. (2002). Relationships between leaf pigment content and spectral reflectance across a wide range of species, leaf structures and developmental stages. Remote Sensing of Environment, 81(2–3), 337–354. https://doi.org/10.1016/S0034-4257(02)00010-X
Wong, C. Y. S., D’Odorico, P., Arain, M. A., & Ensminger, I. (2020). Tracking the phenology of photosynthesis using carotenoid-sensitive and near-infrared reflectance vegetation indices in a temperate evergreen and mixed deciduous forest. New Phytologist, 226(6). https://doi.org/10.1111/nph.16479