Convert raw hyperspectral imaging data (digital numbers) to calibrated reflectance values using white and dark reference measurements. This is the essential first step in hyperspectral data processing.
Usage
hsi_calc_reflectance(
x,
whiteref,
darkref,
darkspec = NULL,
tint = c(1, 1),
in_memory = FALSE,
filename = "",
overwrite = FALSE,
...
)Arguments
- x
A
SpatRasterwith raw hyperspectral sample data. Band names must be numeric wavelengths in nm.- whiteref
A
SpatRasterwith white reference data. Must have the same bands and wavelengths asx.- darkref
A
SpatRasterwith dark reference data from the white reference session. Must have the same bands and wavelengths asx.- darkspec
A
SpatRasterwith dark reference data from the specimen session. DefaultNULL. Required for dual-exposure workflows wheretintvalues differ. WhenNULLandtint = c(1, 1), a single dark reference is sufficient.- tint
Numeric vector of length 2. Integration times for white reference and specimen capture, in that order. Default
c(1, 1)assumes equal integration times.- in_memory
Logical. Process entirely in RAM. Default
FALSE. SetTRUEonly when data fits comfortably in available memory.- filename
Character. Output filename. Default
""keeps result in memory.- overwrite
Logical. Overwrite existing file. Default
FALSE.- ...
Additional arguments passed to
terra::writeRaster().
Value
A SpatRaster with reflectance values.
Details
All inputs must share the same spatial resolution, number of bands,
wavelength labels, and compatible spatial extents. When reading .raw ESRI
data, load with terra::rast(x, noflip = TRUE).
Three calibration paths are supported:
Single session (darkspec = NULL, tint = c(1, 1)): specimen, white
reference, and dark reference all share the same integration time. No
scaling is needed. This is the simplest workflow and produces correct
reflectance, though signal-to-noise is lower than with a dual-exposure
strategy.
Matched darks (darkspec provided): a dual-exposure workflow where the
specimen is overexposed relative to the white reference to maximise signal.
Each subtraction uses the dark reference captured at the matching
integration time. This is the recommended approach for dual-exposure
scanning. Many scanners capture a dark reference per session, so matched
darks are typically available for standard workflows.
$$R(\lambda) = \frac{specimen - dark_{specimen}}{white - dark_{white}} \times \frac{t_{white}}{t_{specimen}}$$
Scaled dark (darkspec = NULL, tint values differ): fallback for
dual-exposure workflows when only the white-session dark reference is
available. The dark reference is scaled by the integration time ratio
before numerator subtraction. This assumes dark current scales linearly
with integration time. In practice, some detectors have a large
fixed-pattern noise component that does not scale with exposure time.
Scaling overestimates the specimen dark current, producing severely
degraded reflectance — often negative across entire spectra. Use only as
a last resort.
$$R(\lambda) = \frac{specimen - dark_{white} \times \frac{t_{specimen}}{t_{white}}}{white - dark_{white}} \times \frac{t_{white}}{t_{specimen}}$$
See also
Other HSI Transformations:
hsi_apply_mnf(),
hsi_calc_difference(),
hsi_calc_mnf(),
hsi_calc_ndi(),
hsi_calc_raba(),
hsi_calc_rabd(),
hsi_calc_ratio(),
hsi_calc_rcv(),
hsi_calc_remp(),
hsi_calc_rmean(),
hsi_calc_rmedian(),
hsi_calc_rsd(),
hsi_calc_stretch(),
hsi_destripe(),
hsi_remove_continuum(),
hsi_smooth_median(),
hsi_smooth_savgol(),
hsi_tiled(),
hsi_write_scaled()
Examples
if (FALSE) { # \dontrun{
x <- terra::rast("capture/testdata.tif")
whiteref <- terra::rast("capture/WHITEREF_testdata.tif")
darkref <- terra::rast("capture/DARKREF_testdata.tif")
# Path 1: single session, equal integration times
x_reflectance <- hsi_calc_reflectance(
x = x,
whiteref = whiteref,
darkref = darkref
)
# Path 2a: matched darks (recommended)
darkspec <- terra::rast("specimen/DARKREF_testdata.tif")
x_reflectance <- hsi_calc_reflectance(
x = x,
whiteref = whiteref,
darkref = darkref,
darkspec = darkspec,
tint = c(3, 9)
)
# Path 2b: scaled dark (single dark, different integration times)
x_reflectance <- hsi_calc_reflectance(
x = x,
whiteref = whiteref,
darkref = darkref,
tint = c(3, 9),
filename = "output_reflectance.tif",
overwrite = TRUE
)
} # }