Package and data preparation
First we need to install required packages and download remote sensing data in Colab and setup working environemnt and directories. Please be sure you have the necessary R packages installed and data downloaded before we begin, as this process can be time-consuming (~30 mins).
#Install and load googledrive package
install.packages("googledrive")
library(googledrive)
# This will prompt you to authenticate in the browser to get access to Google Drive files
drive_auth()
Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) The googledrive package is requesting access to your Google account. Enter '1' to start a new auth process or select a pre-authorized account. 1: Send me to the browser for a new auth process. 2: dmglandon@gmail.com
Selection: 2
#install packages
install.packages("lidR")
install.packages("terra")
install.packages("raster")
install.packages("caret")
install.packages("ggplot2")
install.packages("ggpointdensity")
#Load packages
library(lidR)
library(terra)
library(raster)
library(caret)
library(sp)
library(sf)
library(dplyr)
library(tools)
library(ggplot2)
library(ggpointdensity)
Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) also installing the dependencies ‘proxy’, ‘wk’, ‘e1071’, ‘htmlwidgets’, ‘s2’, ‘units’, ‘abind’, ‘classInt’, ‘lazyeval’, ‘Rcpp’, ‘rgl’, ‘rlas’, ‘sf’, ‘stars’, ‘terra’, ‘BH’, ‘RcppArmadillo’ Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) also installing the dependency ‘sp’ Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) also installing the dependencies ‘listenv’, ‘parallelly’, ‘future’, ‘globals’, ‘shape’, ‘future.apply’, ‘numDeriv’, ‘progressr’, ‘SQUAREM’, ‘diagram’, ‘lava’, ‘prodlim’, ‘iterators’, ‘clock’, ‘gower’, ‘hardhat’, ‘ipred’, ‘timeDate’, ‘foreach’, ‘ModelMetrics’, ‘plyr’, ‘pROC’, ‘recipes’, ‘reshape2’ Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) Installing package into ‘/usr/local/lib/R/site-library’ (as ‘lib’ is unspecified) terra 1.7.71 Attaching package: ‘terra’ The following objects are masked from ‘package:lidR’: area, crs, crs<-, is.empty Loading required package: sp Attaching package: ‘sp’ The following object is masked from ‘package:lidR’: wkt Attaching package: ‘raster’ The following objects are masked from ‘package:lidR’: projection, projection<- Loading required package: ggplot2 Loading required package: lattice Linking to GEOS 3.11.1, GDAL 3.6.4, PROJ 9.1.1; sf_use_s2() is TRUE Attaching package: ‘sf’ The following object is masked from ‘package:lidR’: st_concave_hull Attaching package: ‘dplyr’ The following objects are masked from ‘package:raster’: intersect, select, union The following objects are masked from ‘package:terra’: intersect, union The following objects are masked from ‘package:stats’: filter, lag The following objects are masked from ‘package:base’: intersect, setdiff, setequal, union
#Make directory for inputs and results first
#Download LiDAR and SAR data under the folders "LiDAR" and "SAR"
dir.create("/content/sample_data/Data")
dir.create("/content/sample_data/Result")
dir.create("/content/sample_data/Data/LiDAR")
dir.create("/content/sample_data/Data/SAR")
dir.create("/content/sample_data/Result/CHM")
dir.create("/content/sample_data/Result/Grid_75m")
Warning message in dir.create("/content/sample_data/Data"): “'/content/sample_data/Data' already exists” Warning message in dir.create("/content/sample_data/Result"): “'/content/sample_data/Result' already exists” Warning message in dir.create("/content/sample_data/Data/LiDAR"): “'/content/sample_data/Data/LiDAR' already exists” Warning message in dir.create("/content/sample_data/Data/SAR"): “'/content/sample_data/Data/SAR' already exists” Warning message in dir.create("/content/sample_data/Result/CHM"): “'/content/sample_data/Result/CHM' already exists” Warning message in dir.create("/content/sample_data/Result/Grid_75m"): “'/content/sample_data/Result/Grid_75m' already exists”
#This section is to download remote sensing datasets from Google Drive to Colab file
# List all folders in the root of Google Drive
drive_ls(path = "https://drive.google.com/drive/folders/135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp")
# List all files in the specified Google Drive SAR folder URL
files_SAR <- drive_ls(path = "https://drive.google.com/drive/folders/1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6")
# Loop through the list of file names in the SAR directory
for (i in 1:length(files_SAR[[2]])){
print(i)
# Print a message to the console indicating the start of the download process
print(paste0("Downloading SAR file...",files_SAR[[1]][i]))
# Retrieve the file object from Google Drive using its ID
file <- drive_get(as_id(files_SAR[[2]][i]))
# Download the file to a specified local path in the Colab environment
drive_download(file, path = paste0("/content/sample_data/Data/SAR/",files_SAR[[1]][i]))
}
# List all files in the specified Google Drive LiDAR folder URL
files_LiDAR <- drive_ls(path = "https://drive.google.com/drive/folders/1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr")
# Loop through the list of file names in the LiDAR directory
for (i in 1:length(files_LiDAR[[2]])){
# Print a message to the console indicating the start of the download process
print(paste0("Downloading LiDAR file...",files_LiDAR[[1]][i]))
# Retrieve the file object from Google Drive using its ID
file <- drive_get(as_id(files_LiDAR[[2]][i]))
# Download the file to a specified local path in the Colab environment
drive_download(file, path = paste0("/content/sample_data/Data/LiDAR/",files_LiDAR[[1]][i]))
}
name | id | drive_resource | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
<chr> | <drv_id> | <list> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
File | 14aPl0JC61BShm_DJId-m_TESTycjGlu3 | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/14aPl0JC61BShm_DJId-m_TESTycjGlu3 | TRUE | FALSE | drive | #8f8f8f | 14aPl0JC61BShm_DJId-m_TESTycjGlu3 | File | FALSE | FALSE | FALSE | 2024-05-03T04:31:49.162Z | 2024-05-03T04:31:49.162Z | 0 | 5 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | TRUE | FALSE | drive | #8f8f8f | 1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | Exercise | FALSE | FALSE | FALSE | 2024-05-03T03:57:54.269Z | 2024-05-03T03:57:54.269Z | 0 | 9 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | TRUE | FALSE | drive | #8f8f8f | 1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | SAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:07.435Z | 2024-05-01T18:46:07.435Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | TRUE | FALSE | drive | #8f8f8f | 1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | LiDAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:11.215Z | 2024-05-01T18:46:11.215Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE |
Exercise | 1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/14aPl0JC61BShm_DJId-m_TESTycjGlu3 | TRUE | FALSE | drive | #8f8f8f | 14aPl0JC61BShm_DJId-m_TESTycjGlu3 | File | FALSE | FALSE | FALSE | 2024-05-03T04:31:49.162Z | 2024-05-03T04:31:49.162Z | 0 | 5 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | TRUE | FALSE | drive | #8f8f8f | 1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | Exercise | FALSE | FALSE | FALSE | 2024-05-03T03:57:54.269Z | 2024-05-03T03:57:54.269Z | 0 | 9 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | TRUE | FALSE | drive | #8f8f8f | 1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | SAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:07.435Z | 2024-05-01T18:46:07.435Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | TRUE | FALSE | drive | #8f8f8f | 1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | LiDAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:11.215Z | 2024-05-01T18:46:11.215Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE |
SAR | 1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/14aPl0JC61BShm_DJId-m_TESTycjGlu3 | TRUE | FALSE | drive | #8f8f8f | 14aPl0JC61BShm_DJId-m_TESTycjGlu3 | File | FALSE | FALSE | FALSE | 2024-05-03T04:31:49.162Z | 2024-05-03T04:31:49.162Z | 0 | 5 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | TRUE | FALSE | drive | #8f8f8f | 1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | Exercise | FALSE | FALSE | FALSE | 2024-05-03T03:57:54.269Z | 2024-05-03T03:57:54.269Z | 0 | 9 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | TRUE | FALSE | drive | #8f8f8f | 1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | SAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:07.435Z | 2024-05-01T18:46:07.435Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | TRUE | FALSE | drive | #8f8f8f | 1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | LiDAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:11.215Z | 2024-05-01T18:46:11.215Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE |
LiDAR | 1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/14aPl0JC61BShm_DJId-m_TESTycjGlu3 | TRUE | FALSE | drive | #8f8f8f | 14aPl0JC61BShm_DJId-m_TESTycjGlu3 | File | FALSE | FALSE | FALSE | 2024-05-03T04:31:49.162Z | 2024-05-03T04:31:49.162Z | 0 | 5 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | TRUE | FALSE | drive | #8f8f8f | 1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7 | Exercise | FALSE | FALSE | FALSE | 2024-05-03T03:57:54.269Z | 2024-05-03T03:57:54.269Z | 0 | 9 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | TRUE | FALSE | drive | #8f8f8f | 1Wiec_oIYPNdG70irKLj3O_7wT0I0LOp6 | SAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:07.435Z | 2024-05-01T18:46:07.435Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE | drive#file | FALSE | TRUE | FALSE | application/vnd.google-apps.folder | 135hqF1uEu7Jm4a6PT0FvbhklQZJvJDbp | https://drive-thirdparty.googleusercontent.com/16/type/application/vnd.google-apps.folder+shared | TRUE | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | xiaoxuan.li | drive#user | FALSE | 03290509804548951174 | xiaoxuan.li@nltgis.com | https://lh3.googleusercontent.com/a-/ALV-UjXu_Y7G12Gx0Fpjc5beDxN4RpvX-GThXsnIwfTYQBkFd-a7WA=s64 | https://drive.google.com/drive/folders/1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | TRUE | FALSE | drive | #8f8f8f | 1LKoJxJMn-rSofrkNKEnFmidjq6U7vrlr | LiDAR | FALSE | FALSE | FALSE | 2024-05-01T18:46:11.215Z | 2024-05-01T18:46:11.215Z | 0 | 14 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE | 0 | FALSE | FALSE | TRUE |
[1] 1 [1] "Downloading SAR file...SAR_0826_msf.tif.aux.xml"
Error in `drive_download()`: ! Local `path` already exists and overwrite is `FALSE`: • /content/sample_data/Data/SAR/SAR_0826_msf.tif.aux.xml Traceback: 1. drive_download(file, path = paste0("/content/sample_data/Data/SAR/", . files_SAR[[1]][i])) 2. drive_abort(c("Local {.arg path} already exists and overwrite is {.code FALSE}:", . bulletize(gargle_map_cli(path, "{.path <<x>>}")))) 3. cli::cli_abort(message = message, ..., .envir = .envir) 4. rlang::abort(message, ..., call = call, use_cli_format = TRUE, . .frame = .frame) 5. signal_abort(cnd, .file)
ABSTRACT¶
This tutorial provides guidance on creating a predictive modeling workflow to quantify woody cover from remote sensing datasets (Airborne Light Detection and Ranging (LiDAR) and Synthetic Aperture Radar (SAR)). The methods introduced in the training module were inspired by “Quantifying the sensitivity of L-Band SAR to a decade of vegetation structure changes in savannas” (Wessels et al., 2023, Remote Sensing of Environment).
Title: Quantifying the sensitivity of L-Band SAR to a decade of vegetation structure changes in savannas
Link to the published paper: https://doi.org/10.1016/j.rse.2022.113369
Background¶
In this workshop, we will guide you through the procedures for processing and analyzing airborne LiDAR and SAR data using R. We'll be working with two datasets: the L-band ALOS-2 PALSAR-2 ScanSAR data from JAXA and discrete-return point cloud from airborne LiDAR surveys conducted over the Brazilian Amazon, both of which were collected in 2018. We will use the airborne LiDAR data as a reference to train models for estimating woody cover based on SAR data. The final output is SAR-predicted woody cover maps. We will begin by providing an overview of the research context and the overall workflow used to process and analyze remote sensing data.
Woody cover estimation: Woody cover is a simple, and widely used, two-dimensional structural indicator that can provide landscape level information regarding spatial extent and heterogeneity of woody vegetation, habitat fragmentation, and patchiness (Turner and Gardner, 2001). This estimation is often conducted using remote sensing techniques, including satellite imagery, aerial photography, or LiDAR data, in combination with various analytical methods. Woody cover estimation plays a critical role in ecosystem management, conservation, and land use planning, helping to inform decision-making processes and support sustainable development practices.
Remote sensing: Remote sensing techniques are extensively used to estimate woody cover in large areas due to their ability to cover vast and inaccessible terrains efficiently and cost-effectively. This allows for consistent and non-intrusive monitoring of large-scale environmental changes. Remote sensing is particularly useful for managing resources, planning conservation efforts, and monitoring ecological dynamics, offering a crucial tool in tackling environmental challenges like climate change and biodiversity loss. In this workshop we mainly introduce two remote sensing datasets: Airborne Light Detection and Ranging (LiDAR) and Synthetic-aperture radar (SAR).
Airborne Light Detection and Ranging (LiDAR): airborne LiDAR is a remote sensing technology that uses laser light to create detailed 3D maps of terrain, vegetation, and structures from an aircraft. It provides detailed and accurate data on three-dimensional woody vegetation structure (Camarretta et al., 2019) and has been widely used to conduct research into some of the foremost ecological topics (Asner et al., 2016; Davies et al., 2018; Dean et al., 1999; Fisher et al., 2012, 2015; Levick et al., 2009; Mograbi et al., 2017, 2015; Wessels et al., 2013, 2011).
Synthetic-aperture radar (SAR): SAR instrument such as Advanced Land Observing Satellite-2 (ALOS-2) Phased Arrayed L-band Synthetic Aperture Radar-2 (PALSAR-2) is an active microwave remote sensing sensor that operates independently of energy from the sun or other light sources, meaning that it works equally well during the day and night. Furthermore, SAR also has the capability to provide global wall-to-wall coverage in all weather conditions and is less affected by clouds and rains (Flores-Anderson et al., 2019). SAR backscatter refers to the way the radar signal is reflected back to the satellite or aircraft from the surface. In the case of L-band SAR, the backscatter is influenced by the surface roughness, moisture content, and vegetation structure. Recent studies have demonstrated that L-band SAR (e.g., ALOS-2 PALSAR-2 ScanSAR) backscatter has a much stronger relationship with woody vegetation cover and biomass than shorter wavelength, X-band or C-band SAR (Main et al., 2016; Mathieu et al., 2013; Urbazaev et al., 2015). The ability of L-band SAR to penetrate vegetation and its sensitivity to moisture make it particularly useful for applications such as vegetation structure and biomass estimation.
Data structure: In geospatial data analysis, data can be classified into two categories: raster and vector data. A graphic comparison between raster and vector data can be found on this page.
Raster data: Data stored in a raster format is arranged in a regular grid of cells, without storing the coordinates of each point (namely, a cell, or a pixel). Raster data is commonly stored in Tagged Image File Format (TIFF or TIF). A GeoTIFF is a TIFF file that follows a specific standard for structuring meta-data. The meta-data stored in a TIFF is called a tif tag and GeoTIFFs often contain tags including spatial extent, coordinate reference system, resolution, and number of layers.
Vector data: Data in a vector format is stored such that the X and Y coordinates are stored for each point. Data can be represented, for example, as points, lines and polygons. Vector data stores features in their original resolution, without aggregation. Geospatial data in vector format are often stored in a shapefile format. Airborne LiDAR point clouds are considered to be vector data. A point cloud is a collection of data points defined in a given coordinate system. In a point cloud, each point represents a single sample of an object's surface set in its own discrete location in three-dimensional space.
Tools:
- R: R is a powerful programming language and software environment primarily used for statistical computing and graphics. It is widely favored for data analysis, statistical modeling, and visualization, and is supported by a vibrant community that contributes packages for various scientific and analytical applications. To get started with R, we provide instructions on how to download and install R on your computer. R is an open source software, which means users like you can also inspect, modify, and improve its source code. The Comprehensive R Archive Network (CRAN) provides links to easily install R packages under different operating systems.
R homepage : https://cran.r-project.org/bin/windows/base/
- RStudio (PC preferred): RStudio serves as an IDE designed for R programming. While R provides the underlying engine for executing code, RStudio offers an intuitive control panel for executing diverse tasks. It simplifies tasks such as writing and debugging R code and offers tools for efficient workspace management. To access RStudio, users can download it from the RStudio IDE page.
R Studio homepage: https://posit.co/download/rstudio-desktop/
- Google Colaboratory (Workshop preferred): Google Colaboratory (Colab), is a free cloud service offered by Google that allows users to write and execute Python code collaboratively. It's based on Jupyter Notebooks and provides an environment where you can write and execute Python code in your browser. While Colab primarily supports Python, you can also run R code in Colab notebooks which enables interoperability between Python and R.
Colab homepage: https://colab.research.google.com/
- R environment setup: To conduct data manipulation, it's necessary to load packages. Initially, we download R packages from CRAN. For this task, we'll utilize several packages:
- lidR for point cloud data processing
- terra (including sf) and raster (including sp) for raster data processing
- ggplot and ggpointdensity for visualization
- tools and dplyr for data manipulation
- caret for training regression models.
Data introduction, processing and analysis¶
In this section, we mainly introduce the study area, datasets, and methods we used to predict woody cover in Brazil.
Airborne LiDAR
The airborne LiDAR data used in this workshop provides the subset of point cloud data collected during LiDAR surveys over selected forest research sites across the Amazon rainforest in Southern Santarem, Brazil in 2018. The point clouds have been georeferenced, noise-filtered, and corrected for misalignment of overlapping flight lines. They are provided in 1 km2 tiles. The original ALS point cloud were used to generate 1 m Canopy height models (CHMs) mosaic using lidR package in R. The 1 m CHMs were used to calculate ALS canopy cover metrics for each corresponding 15 m SAR pixel. The 15 m grid was created in ArcGIS Pro using “create fishnet” function. ALS cover fraction was calculated summing the total number of 1 m CHM pixels with heights above 1.5 m and dividing by the total number of CHM pixels in each 15 m SAR pixel. This ALS CHM-derived canopy cover has been proven to have a strong relationship with biomass within the study area (Colgan et al., 2012).
Airborne LiDAR data page via NASA EarthData: https://search.earthdata.nasa.gov/search/granules?p=C2398128915-ORNL_CLOUD&pg[0][v]=f&pg[0][gsk]=-start_date&q=laz&tl=1712691638.776!3!!
Airborne LiDAR metadata: https://daac.ornl.gov/CMS/guides/LiDAR_Forest_Inventory_Brazil.html
Here is the R code to batch process LiDAR point cloud data to create Canopy Height Models (CHM):
# ------------------------------------------------------------------------------------------------ #
# Batch preprocessing of LiDAR point cloud data to create Canopy Height Models (CHM)
dir <- "/content/sample_data/Data/LiDAR" # Directory containing input LiDAR files
output = "/content/sample_data/Result/CHM" # Output directory for the CHM TIFF files
las_files = list.files(dir, pattern = glob2rx('*.laz'), full.names = T) # List all .laz files in the directory with full paths
for (i in las_files){ # Loop over each LiDAR file in the list
out = file.path(output, paste0(basename(file_path_sans_ext(i)), ".tif")) # Create a filepath for the output .tif file using the base name of the input file
if (!file.exists(out)) # Check if the output file already exists to avoid overwriting
{
print(i) # Print the current file being processed
print("read ALS") # Indicate start of reading the LiDAR (ALS) data
las <- readLAS(i, select = "i,c,r") # Read the .laz file with intensity, class, and return number
print("normalize ALS") # Indicate start of height normalization
las = normalize_height(las, tin(), na.rm = TRUE) # Normalize point cloud heights using a Triangulated Irregular Network (TIN)
print("filter out ALS point cloud > 100m") # Indicate filtering action
las <- filter_poi(las, Z >= 0, Z <= 100) # Filter points to include only those between 0 and 100 meters
print("1m CHM generation") # Indicate start of Canopy Height Model generation
chm <- grid_canopy(las, 1, p2r()) # Generate a CHM with a grid cell size of 1 meter
projection(chm) <- CRS("+proj=utm +zone=21 +south +datum=WGS84 +units=m +no_defs") # Set the projection information for the CHM
print("Output chm") # Indicate CHM is being outputted
writeRaster(chm, out, options=c('TFW=YES'), overwrite=TRUE) # Write the CHM raster to file with a world file (.tfw) and allow overwriting if needed
}
}
Here is the R code to merge all individual CHM raster files into one raster file.
# ------------------------------------------------------------------------------------------------ #
# Batch process to mosaic individual CHM TIFF files into larger, merged CHM files by site
# Setting up directory paths for individual CHM files and output for merged CHM files
dir_chm = "/content/sample_data/Result/CHM"
# List files matching the current site name and ending with '.tif'
chm_files <- list.files(path = dir_chm, pattern = paste0("TAP_A03_2018", ".*\\.tif$"), full.names = TRUE)
# Load all matching CHM files as raster objects
rasters <- lapply(chm_files, raster)
# Merge all raster objects into a single raster using the 'merge' function
merged_raster <- do.call(merge, rasters)
# Write the merged raster to disk with a filename that includes the site name, in GeoTIFF format, and overwrite if exists
writeRaster(merged_raster, filename = file.path(dir_chm,"TAP_A03_2018_Merge.tif"), format = "GTiff", overwrite = TRUE)
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=12)
#Let's visualize the mosaic CHM dataset for all LiDAR tiles
plot(raster("/content/sample_data/Result/CHM/TAP_A03_2018_Merge.tif"), main="2018 Mosaic LiDAR-based CHM map")
# Specify the output directory where the modified raster will be saved
output = "/content/sample_data/Result/CHM"
# Load the raster file from the specified directory
ras <- merged_raster
# Set raster values less than 1.5 and greater than 0 to 0 (e.g., treat as non-woody vegetation)
values(ras)[values(ras) < 1.5] <- 0
# Set raster values equal to or greater than 1.5 to 1 (e.g., treat as woody cover)
values(ras)[values(ras) >= 1.5] <- 1
# Write the modified raster back to file with the specified name and enable the TFW option, allowing overwriting of the existing file if necessary
writeRaster(ras, file.path(output, "TAP_A03_2018_cover.tif"), options=c('TFW=YES'), overwrite=TRUE)
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=12)
#Let's visualize the woody cover for all LiDAR tiles
plot(raster("/content/sample_data/Result/CHM/TAP_A03_2018_cover.tif"), main="2018 Mosaic LiDAR-based woody cover map")
SAR
In this workshop, we used JAXA's L-band ALOS-2 PALSAR-2 ScanSAR (L2.2) which was projected to UTM 21S and was already pre-processed (i.e. geocoding and radiometric terrain correction). After downloading the ScanSAR data from Google Earth Engine (GEE), several pre-processing steps were developed and implemented to further improve ALOS-2 PALSAR-2 performance, including DN conversion and multi-speckle filtering:
The Digital Number (DN) values of original ALOS-2 PALSAR-2 were converted to sigma naught values (σ0) in decibel unit (dB)using the following equation: σ0 = 10*log10(DN^2) - 83.0
The multi-temporal speckle filtering method was applied to reduce the speckle noise (Bruniquel and Lopes, 1997; Quegan and Yu, 2001).
ALOS-2 PALSAR-2 ScanSAR download via JAXA G-Portal: https://gportal.jaxa.jp/gpr/search?tab=1
ALOS-2 PALSAR-2 ScanSAR download via GEE: https://github.com/Shawn4889/ALOS2_GEE/blob/main/ALOS_GEE
ALOS-2 PALSAR-2 ScanSAR metadata: https://www.eorc.jaxa.jp/ALOS/en/dataset/palsar2_l22_e.htm
Multi-temporal speckle filtering link: https://github.com/Shawn4889/mult_temp_speckle_filter/blob/main/mult_temp_speckle_filter.py
These preprocessing steps were originally developed in Python and will not be covered in this workshop. Instead, we only focus on visualizing the original and multi-temporal speckle filtering (MSF) SAR backscatter for comparison purposes.
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=12)
# Load the first raster file into the 'raster1' object from the specified path
raster1 <- raster("/content/sample_data/Data/SAR/SAR_0826.tif")
# Load the second raster file into the 'raster2' object from the specified path
raster2 <- raster("/content/sample_data/Data/SAR/SAR_0826_msf.tif")
# Plot the whole extent of the clipped ScanSAR data
plot(raster2, main="2018 MSF ScanSAR", zlim=c(-30,0), col=terrain.colors(255))
# Define a new spatial extent to be applied to both rasters
new_extent <- extent(759000, 760000, 9663600, 9664600)
# Crop 'raster1' to the defined spatial extent and store the result in 'raster1_cropped'
raster1_cropped <- crop(raster1, new_extent)
# Crop 'raster2' to the same defined spatial extent and store the result in 'raster2_cropped'
raster2_cropped <- crop(raster2, new_extent)
# Set the size of plots in Google Colab
options(repr.plot.width=6, repr.plot.height=6)
# Plot the cropped area of 'raster2' with a title and a terrain color scheme, indicating multi-spectral filtering (MSF)
plot(raster2_cropped, main="Subset of 2018 MSF ScanSAR", col=terrain.colors(255))
# Plot the cropped area of 'raster1' with a title and a terrain color scheme
plot(raster1_cropped, main="Subset of 2018 original ScanSAR", col=terrain.colors(255))
Grids are required to match SAR and LiDAR to develop woody cover models. The following codes produce the 75m (3x3x25m) grid for statistical analysis.
# ------------------------------------------------------------------------------------------------ #
# Create a 75m grid based on the extent of a LiDAR-derived 25m resolution raster
# Load the 25m resolution raster from a specified path
raster25m <- raster("/content/sample_data/Result/CHM/TAP_A03_2018_cover.tif")
# Create an empty raster with a 75m resolution using the extent and CRS of the 25m raster
raster75m <- raster(extent(raster25m), res=75, crs=crs(raster25m))
# Adjust the origin of the 75m raster to match that of the 25m raster
# This ensures that the grid cells of both rasters align perfectly if they cover the same area
origin(raster75m) <- origin(raster25m)
# Initialize the raster's values. Here, assigning a unique ID to each cell, which can be useful for tracking or identification
# This step is optional and could instead fill with random values or other data as needed
values(raster75m) <- 1:ncell(raster75m)
# Convert the 75m grid raster to polygons
# This creates a polygon for each unique value (cell) in the raster, dissolving all borders within the same value
polygons <- rasterToPolygons(raster75m, fun=NULL, dissolve=TRUE)
# Convert the resulting polygons from SpatialPolygonsDataFrame to an sf object for better handling in modern GIS operations
sf_object <- st_as_sf(polygons)
# Write the sf object to a shapefile, deleting any existing layer with the same name to avoid errors
st_write(sf_object, "/content/sample_data/Result/Grid_75m/Grid_75m.shp", delete_layer = TRUE)
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=6)
# Plot the 75m grid in raster format
plot(sf_object, main="75m vector grid", col=rgb(runif(20), runif(20), runif(20)))
writing: substituting ENGCRS["Undefined Cartesian SRS with unknown unit"] for missing CRS
Writing layer `Grid_75m' to data source `/content/sample_data/Result/Grid_75m/Grid_75m.shp' using driver `ESRI Shapefile' Writing 1924 features with 1 fields and geometry type Polygon.
Warning message in plot.sf(sf_object, main = "75m vector grid", col = rgb(runif(20), : “col is not of length 1 or nrow(x): colors will be recycled; use pal to specify a color palette”
The next step is to aggregate 25m SAR and 1m LiDAR-based woody cover to 75m using the 75m grid:
# ------------------------------------------------------------------------------------------------ #
# Aggregate 25m SAR and 1m LiDAR-derived woody cover to 75m using zonal statistics
# Load the SAR raster data from a file, which will be analyzed to compute mean values within each zone
value_raster_SAR <- rast("/content/sample_data/Data/SAR/SAR_0826_msf.tif")
# Load the LiDAR-derived woody cover raster data from a file, which will be analyzed to compute sum values within each zone
value_raster_Cover <- rast("/content/sample_data/Result/CHM/TAP_A03_2018_cover.tif")
# Load the shapefile defining the zones for which statistics will be calculated
zones <- vect("/content/sample_data/Result/Grid_75m/Grid_75m.shp")
# Calculate mean zonal statistics for the SAR data within each 75m grid zone
zonal_stats_SAR <- zonal(value_raster_SAR, zones, "mean")
# Calculate sum zonal statistics for the LiDAR-derived cover data within each 75m grid zone
zonal_stats_Cover <- zonal(value_raster_Cover, zones, "sum")
# Normalize the summed LiDAR cover data by the total number of 1m pixels within a 75m pixel
# Assuming a 75m x 75m grid implies 5625 (75*75) 1m pixels per grid cell
zonal_stats_Cover$TAP_A03_2018_cover <- zonal_stats_Cover$TAP_A03_2018_cover / 5625
# Assign a unique ID to each zone for SAR statistics for later merging and comparison
zonal_stats_SAR$ID <- c(1:nrow(zonal_stats_SAR))
# Assign a unique ID to each zone for cover statistics for later merging and comparison
zonal_stats_Cover$ID <- c(1:nrow(zonal_stats_Cover))
# Merge the SAR and cover statistics into a single dataframe based on their IDs
Data_SAR_Cover <- merge(x = zonal_stats_SAR, y = zonal_stats_Cover, by.x = "ID", by.y = "ID")
# Remove all rows with NA values, which might result from zones not covered by both datasets
Data_SAR_Cover <- na.omit(Data_SAR_Cover)
# Rename columns to reflect the data they represent
names(Data_SAR_Cover) <- c("ID", "SAR", "Cover")
# Round the cover and SAR data to three decimal places for cleaner presentation and analysis
Data_SAR_Cover$Cover <- round(Data_SAR_Cover$Cover, 3)
Data_SAR_Cover$SAR <- round(Data_SAR_Cover$SAR, 3)
# Filter the data to include only rows where cover is greater than 0 and less than 1
# This step assumes cover is a proportion or percentage that should logically fall between 0 and 1
Data_SAR_Cover <- Data_SAR_Cover[Data_SAR_Cover$Cover > 0,]
Data_SAR_Cover <- Data_SAR_Cover[Data_SAR_Cover$Cover < 1,]
# Print or view the first 20 rows of cleaned, joined data table
head(Data_SAR_Cover, 10)
ID | SAR | Cover | |
---|---|---|---|
<int> | <dbl> | <dbl> | |
39 | 39 | -15.611 | 0.454 |
40 | 40 | -15.333 | 0.580 |
41 | 41 | -15.891 | 0.883 |
42 | 42 | -14.203 | 0.881 |
59 | 59 | -20.579 | 0.133 |
60 | 60 | -21.045 | 0.073 |
61 | 61 | -21.321 | 0.092 |
62 | 62 | -19.601 | 0.123 |
63 | 63 | -18.192 | 0.034 |
64 | 64 | -16.344 | 0.102 |
Predictive modeling: An overview of the analysis workflow is given and detailed in subsections below. The ALS data were processed to canopy height, cover and volume within the extent of 15 m SAR pixels. The SAR backscatter and ALS cover and volume metrics were compared after aggregating the 15 m resolution data to a 5 × 5, or 75 m moving window. The relationship between PALSAR backscatter and volume or cover was investigated for individual years, using a logarithmic model. The next step was to invert these models to make gridded datasets for cover and volume for individual years from the SAR data. All models were run 10 times using a different, randomly selected 70% subset of data for model development and the remaining 30% for validation, while the mean results of the 30 repetitions were reported. The predicted woody cover estimates were evaluated based on several accuracy metrics and error measures, such as ccoefficient of determination (R2), bias, and RMSE.
R code to examine the relationship between woody cover and SAR backscatter:
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=12)
r2 <- round(cor(Data_SAR_Cover$SAR,Data_SAR_Cover$Cover)^2,3)
# Create a scatter plot with density coloring and add a linear regression line
ggplot(Data_SAR_Cover, aes(x = Cover, y = SAR)) +
theme_bw() + # Use a theme with a white background and no grid
geom_pointdensity() + # Create a density scatter plot
geom_smooth(
method = "lm", # Linear model
formula = y ~ x, # Formula for the linear model
se = FALSE, # Do not include a confidence interval around the regression line
size = 1.5, # Set the size of the regression line
linetype = "solid", # Use a solid line
colour = "red" # Color the line red
) +
annotate("text", x = 0.35, y = -21, hjust = 0, color = "red", size = 7,
label = paste(expression(Linear ~ model ~ R^2), ": ", r2), parse = TRUE) +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
labs(
x = "Mean of Woody cover (Mg/ha)", # X-axis label
y = "Mean of SAR backscatter (dB)" # Y-axis label
) +
theme(
legend.position = "none", # Remove the legend
legend.title = element_blank(), # Remove the legend title
text = element_text(size = 25), # Increase text size for better readability
# Uncomment the following line to set a specific font family
# text = element_text(family = "A"),
plot.title = element_text(hjust = 0.5) # Center the plot title
)
Warning message:
“Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.”
R code to develop linear regression model and evaluate the model performance using statistical measures:
# ------------------------------------------------------------------------------------------------ #
# Grouping data into intervals and ordering by group
Data_SAR_Cover <- Data_SAR_Cover %>%
group_by(gr = cut(Cover, breaks = seq(0, 1, by = 0.1))) %>%
arrange(as.numeric(gr))
# Initialize variables
i <- 1
rsqd_sample <- numeric(10)
bias_sample <- numeric(10)
RMSE_sample <- numeric(10)
raster_list <- vector("list", 10)
# Loop to perform operations 10 times
for (i in 1:10){
# Partitioning the data into training and testing sets (70% training data)
random_sample <- createDataPartition(Data_SAR_Cover$Cover, p = 0.7, list = FALSE)
training_dataset <- Data_SAR_Cover[random_sample, ]
testing_dataset <- Data_SAR_Cover[-random_sample, ]
# Linear regression model
reg <- lm(Cover ~ SAR, data = training_dataset)
testing_dataset$preds <- predict(reg, newdata = testing_dataset)
# Calculating performance metrics
rsqd_sample[i] <- round(cor(testing_dataset$Cover, testing_dataset$preds)^2, 3)
bias_sample[i] <- mean(testing_dataset$preds - testing_dataset$Cover)
RMSE_sample[i] <- sqrt(mean((testing_dataset$preds - testing_dataset$Cover)^2))
# Creating raster map using regression coefficients
value_raster_SAR <- raster("/content/sample_data/Data/SAR/SAR_0826_msf.tif")
SAR_cover <- value_raster_SAR * reg$coefficients[2] + reg$coefficients[1]
raster_list[[i]] <- SAR_cover # Storing raster in list
}
# Calculating average of the performance metrics
R2_testing <- mean(rsqd_sample)
bias_testing <- mean(bias_sample)
RMSE_testing <- mean(RMSE_sample)
# Print the results
cat("Average R-squared:", R2_testing, "
")
cat("Average Bias:", bias_testing, "
")
cat("Average RMSE:", RMSE_testing, "
")
Error in eval(expr, envir, enclos): object 'Data_SAR_Cover' not found Traceback: 1. Data_SAR_Cover %>% group_by(gr = cut(Cover, breaks = seq(0, 1, . by = 0.1))) %>% arrange(as.numeric(gr)) 2. arrange(., as.numeric(gr)) 3. group_by(., gr = cut(Cover, breaks = seq(0, 1, by = 0.1)))
The resulting SAR-based woody cover map was derived by averaging the 10 resulting maps:
# ------------------------------------------------------------------------------------------------ #
# Stack raster layers from the list into a single raster stack
raster_stack <- stack(raster_list)
# Calculate the mean of all rasters in the stack
raster_mean <- mean(raster_stack)
#limit woody cover map to specific range
raster_mean[raster_mean < 0] <- 0
raster_mean[raster_mean > 1] <- 1
# Specify the file path and name for the output raster
output_SAR_cover <- "/content/sample_data/Result/SAR_cover_75m.tif"
# Write the mean raster to a GeoTIFF file at the specified location
# This saves the raster permanently to disk for further use
writeRaster(raster_mean, filename=output_SAR_cover, format="GTiff", overwrite=TRUE)
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=12)
# Plot the mean woody cover raster to visualize the average values
plot(raster_mean, zlim=c(0, 1), main="Mean SAR-predicted woody cover map")
#remove stack raster from memory to avoid program crash
rm(raster_stack)
Uncertainty analysis: Uncertainty assessment is important because it helps quantify the confidence in the results obtained from data analysis, providing a measure of reliability. This assessment informs decision-makers about the potential risk and variability in predictions, guiding better and more informed decisions. Additionally, it identifies the limits of current knowledge and highlights areas where more data or refined models may be necessary.
# ------------------------------------------------------------------------------------------------ #
# Define break points for bins from 0 to 1, at intervals of 0.1
breakbin = seq(0, 1, by = 0.1)
# Calculate the difference between predictions and actual cover values, store in new column 'Diff'
testing_dataset$Diff <- testing_dataset$preds - testing_dataset$Cover
# Group 'Diff' by binned 'Cover', calculate mean for each bin
a <- tapply(testing_dataset$Diff, cut(testing_dataset$Cover, breaks = breakbin, dig.lab = 1), mean)
# Generate sequence from 0 to 0.9 for x-axis labels, rounded to one decimal place
x <- round(seq(0, 0.9, by = 0.1), digits = 1)
# Combine 'x' and 'a' into a matrix
l <- cbind(x, a)
# Convert the matrix to a dataframe for plotting
df <- data.frame(l)
# Set the size of plots in Google Colab
options(repr.plot.width=12, repr.plot.height=12)
# Create a ggplot: bars shifted right by 0.05 for centering, using the dataframe 'df'
ggplot(df, aes(x = x + 0.05, y = a)) +
geom_bar(stat = 'identity') + # Plot bars representing data
theme_bw() + # Use a minimal theme with white background
coord_cartesian(ylim = c(-0.2, 0.3)) + # Set y-axis limits
scale_y_continuous(minor_breaks = seq(-0.2, 0.3, 0.1), breaks = seq(-0.2, 0.3, 0.1)) + # Define breaks for y-axis
scale_x_continuous(minor_breaks = round(seq(0, 1, 0.1), digits = 1), # Minor x-axis breaks
breaks = round(seq(0, 1, 0.1), digits = 1)) + # Major x-axis breaks
labs(x = expression("Woody cover interval"), # X-axis label
y = expression("Woody cover difference")) + # Y-axis label
theme(legend.position = "none") + # Remove legend
theme(legend.title = element_blank()) + # Remove legend title
theme(text = element_text(size = 25)) + # Set text size for all text elements
theme(plot.title = element_text(hjust = 0.5)) # Center the plot title horizontally
Error in eval(expr, envir, enclos): object 'testing_dataset' not found Traceback:
Exercise 1¶
What if we use logarithm model, not linear model? Which one is better for our case study and why?
# Statistics and plots using logarithmic model
# Calculate the R^2 value for the relationship between SAR and log(Cover) and round it to three decimal places
r2 <- round(cor(Data_SAR_Cover$SAR, log(Data_SAR_Cover$Cover))^2, 3)
# Create a ggplot of log(Cover) vs SAR with a density point
ggplot(Data_SAR_Cover, aes(x=Cover, y=SAR)) +
theme_bw() +
geom_pointdensity() +
geom_smooth(
method = "lm",
formula = 'y ~ log(x)',
se = FALSE,
size = 1.5,
linetype = "solid",
colour = "red"
) +
annotate("text", x = 0.7, y = -20, hjust = 0, color = "red", size = 7,
label = paste(expression(Linear~model~R^2), ": ", r2), parse = TRUE) +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
labs(x = "Mean of Woody cover",
y = "Mean of SAR backscatter (dB)") +
theme(legend.position = "none") +
theme(legend.title = element_blank()) +
theme(text = element_text(size = 30)) +
theme(plot.title = element_text(hjust = 0.5))
# Group and arrange the data based on Cover
Data_SAR_Cover <- Data_SAR_Cover %>%
group_by(gr = cut(Cover, breaks = seq(0, 1, by = 0.1))) %>%
arrange(as.numeric(gr))
# Initialize variables for storing metrics across subsets
rsqd_sample <- numeric(10) # Store R-squared values
bias_sample <- numeric(10) # Store bias values
RMSE_sample <- numeric(10) # Store RMSE values
raster_list <- list() # List to store raster data
# Loop over 10 subsets to calculate metrics for each
for (i in 1:10) {
random_sample <- createDataPartition(Data_SAR_Cover$Cover, p = 0.7, list = FALSE)
training_dataset <- Data_SAR_Cover[random_sample, ]
testing_dataset <- Data_SAR_Cover[-random_sample, ]
x <- testing_dataset$Cover
y <- testing_dataset$SAR
# Non-linear regression model
mult_nls <- nls(x ~ a * exp(b * y), start = list(a = 20, b = 0.2), data = training_dataset)
testing_dataset$preds <- coef(mult_nls)[1] * exp(coef(mult_nls)[2] * testing_dataset$SAR)
# Calculate R-squared, bias, and RMSE for the testing dataset
rsqd_sample[i] <- round(cor(testing_dataset$Cover, testing_dataset$preds)^2, 3)
bias_sample[i] <- mean(testing_dataset$preds - testing_dataset$Cover)
RMSE_sample[i] <- sqrt(mean((testing_dataset$preds - testing_dataset$Cover)^2))
}
# Calculate average R-squared, bias, and RMSE across all subsets
R2_testing <- mean(rsqd_sample)
bias_testing <- mean(bias_sample)
RMSE_testing <- mean(RMSE_sample)
# Print the results
cat("Average R-squared:", R2_testing, "
")
cat("Average Bias:", bias_testing, "
")
cat("Average RMSE:", RMSE_testing, "
")
Error in eval(expr, envir, enclos): object 'Data_SAR_Cover' not found Traceback: 1. cor(Data_SAR_Cover$SAR, log(Data_SAR_Cover$Cover)) 2. is.data.frame(y)
Exercise 2 (optional)¶
Replicate our methods to different study areas (e.g., ST3_A01_2014_P30) in Brazil.
Conduct multi-speckle filtering analysis on the original SAR data using Python. Hint: download the original SAR file from GEE and run the prompt commend line: python mult_temp_speckle_filter.py SAR_raster_stack.nc -k 5
You can download the Exercise airborne LiDAR and SAR data via the link: https://drive.google.com/drive/folders/1xpeW3XL-B4QH7u26uvsN4v6PT6dHF6D7
Take-home message
- The 2018 LiDAR-based woody cover estimates and SAR backscatter were highly correlated.
- Linear model is better than non-linear model in our case study to predict woody cover from SAR.
- To make the reference LiDAR data more representative, more LiDAR tiles are expected to be included in the analysis.
Reference¶
- Wessels, K., Li, X., Bouvet, A., Mathieu, R., Main, R., Naidoo, L., ... & Asner, G. P. (2023). Quantifying the sensitivity of L-Band SAR to a decade of vegetation structure changes in savannas. Remote Sensing of Environment, 284, 113369.
- Turner, M. G., Gardner, R. H., O'neill, R. V., & O'Neill, R. V. (2001). Landscape ecology in theory and practice (Vol. 401). Springer New York.
- Camarretta, N., Harrison, P. A., Bailey, T., Potts, B., Lucieer, A., Davidson, N., & Hunt, M. (2020). Monitoring forest structure to guide adaptive management of forest restoration: a review of remote sensing approaches. New Forests, 51(4), 573-596.
- Asner, G.P., Vaughn, N., Smit, I.P.J., Levick, S., 2016. Ecosystem-scale effects of megafauna in African savannas. Ecography 39, 240–252.
- Davies, A.B., Gaylard, A., Asner, G.P., 2018. Megafaunal effects on vegetation structure throughout a densely wooded African landscape. Ecol. Appl. 28, 398–408.
- Dean, W.R.J., Milton, S.J., Jeltsch, F., 1999. Large trees, fertile islands, and birds in arid savanna. J. Arid Environ. 41, 61–78.
- Fisher, J., Witkowski, E.T.F., Erasmus, B.F.N., van Aardt, J.A.N., Asner, G.P., Wessels, K. J., Mathieu, R., 2012. Human-modified landscapes: patterns of fine-scale woody vegetation structure in communal savanna rangelands. Environ. Conserv. 39, 72–82.
- Fisher, J.T., Witkowski, E.T., Erasmus, B.F., Mograbi, P.J., Asner, G.P., Aardt, J.A., Wessels, K.J., Mathieu, R., 2015. What lies beneath: detecting sub-canopy changes in savanna woodlands using a three-dimensional classification method. Appl. Veg. Sci. 18, 528–540.
- Levick, S.R., Asner, G.P., Kennedy-Bowdoin, T., Knapp, D.E., 2009. The relative influence of fire and herbivory on savanna three-dimensional vegetation structure. Biol. Conserv. 142, 1693–1700.
- Mograbi, P.J., Asner, G.P., Witkowski, E.T.F., Erasmus, B.F.N., Wessels, K.J., Mathieu, R., Vaughn, N.R., 2017. Humans and elephants as treefall drivers in African savannas. Ecography 40, 1274–1284.
- Mograbi, P.J., Erasmus, B.F.N., Witkowski, E.T.F., Asner, G.P., Wessels, K.J., Mathieu, R., Knapp, D.E., Martin, R.E., Main, R., 2015. Biomass increases Go under cover: Woody vegetation dynamics in South African rangelands. PLoS ONE 10, e0127093. https:// doi.org/10.1371/journal.pone.0127093.
- Wessels, K.J., Colgan, M.S., Erasmus, B.F.N., Asner, G.P., Twine, W.C., Mathieu, R., van Aardt, J.A.N., Fisher, J.T., Smit, I.P.J., 2013. Unsustainable fuelwood extraction from South African savannas. Environ. Res. Lett. 8, 014007
- Wessels, K.J., Mathieu, R., Erasmus, B.F.N., Asner, G.P., Smit, I.P.J., van Aardt, J.A.N., Main, R., Fisher, J., Marais, W., Kennedy-Bowdoin, T., Knapp, D.E., Emerson, R., Jacobson, J., 2011. Impact of communal land use and conservation on woody vegetation structure in the Lowveld savannas of South Africa. For. Ecol. Manag. 261, 19–29.
- Flores-Anderson, A. I., Herndon, K. E., Thapa, R. B., & Cherrington, E. (2019). The SAR handbook: comprehensive methodologies for forest monitoring and biomass estimation (No. MSFC-E-DAA-TN67454).
- Main, R., Mathieu, R., Kleynhans, W., Wessels, K., Naidoo, L., & Asner, G. P. (2016). Hyper-temporal C-band SAR for baseline woody structural assessments in deciduous savannas. Remote Sensing, 8(8), 661.
- Mathieu, R., Naidoo, L., Cho, M. A., Leblon, B., Main, R., Wessels, K., ... & Smit, I. P. (2013). Toward structural assessment of semi-arid African savannahs and woodlands: The potential of multitemporal polarimetric RADARSAT-2 fine beam images. Remote Sensing of Environment, 138, 215-231.
- Urbazaev, M., Thiel, C., Mathieu, R., Naidoo, L., Levick, S. R., Smit, I. P., ... & Schmullius, C. (2015). Assessment of the mapping of fractional woody cover in southern African savannas using multi-temporal and polarimetric ALOS PALSAR L-band images. Remote Sensing of Environment, 166, 138-153.
- Colgan, M. S., Asner, G. P., Levick, S. R., Martin, R. E., & Chadwick, O. A. (2012). Topo-edaphic controls over woody plant biomass in South African savannas. Biogeosciences, 9(5), 1809-1821.
- Bruniquel, J., & Lopes, A. (1997). Multi-variate optimal speckle reduction in SAR imagery. International journal of remote sensing, 18(3), 603-627.
- Quegan, S., & Yu, J. J. (2001). Filtering of multichannel SAR images. IEEE Transactions on geoscience and remote sensing, 39(11), 2373-2379.
Cite this work¶
DOI: https://doi.org/10.1016/j.rse.2022.113369
APA citation: Wessels, K., Li, X., Bouvet, A., Mathieu, R., Main, R., Naidoo, L., ... & Asner, G. P. (2023). Quantifying the sensitivity of L-Band SAR to a decade of vegetation structure changes in savannas. Remote Sensing of Environment, 284, 113369.
Contact:
Xiaoxuan Li: dawn4889@gmail.com