Normalisation of Sentinel-2 BRDF for Sentinel Hub.
The idea of implementing a BRDF normalisation for Sentinel-2 scenes in Sentinel Hub was sparked by a forum post that was published around the same time that Sentinel Hub wrote a medium blog post on how to create global mosaics. At the time I got several questions about the "striping effects" due to surface reflectance anisotropy and started looking into solutions to normalise the reflectance (note: at small scales it often doesn't matter).
It turns out that implementing a solution that is valid for all types of surfaces isn't that easy. Not wanting to re-invent the wheel, the obvious solution is to take an acceptable solution from the scientific literature and implement it as an Evalscript.
A suitable approach that seems to work for most surfaces is the "semi-empirical BRDF normalisation c-factor correction approach proposed by Luch et al. 2000 (see papers folder). The formula is detailed in eq. 37 (using eq. 38 & 39) . But to avoid lookup tables and other complex modelling approaches, we can use the fixed BRDF spectral model parameters derived from "the global year of highest quality snow-free MODIS BRDF product" conveniently defined for Sentinel-2 in Roy et al. 2017 that were derived from the Landsat ones in Roy et al. 2016.
javascript contains all the javascript code, later to be implemented in an Evalscript.
notebooks contains the functions tested against the graphs from the papers used to develop the algorithm.
papers contains the relevant scientific articles.
s2brdf contains a python package implementation of the algorithms.
s2brdf
is a python implementation of the BRDF normalisation process.
Code for the volumetric scattering and geometric-optical model kernels can be found in kernels.py
.
Functions for the nadir-adjusted BRDF reflectance are in brdf.py
.
- Create a virtual environment (optional)
mkvirtualenv s2brdf
- Install using
pip
pip install -e .
coming soon...
To estimate geometric kernel values (k_geo
), you can pass a vector of solar zenith angle (sza
), view zenith angle (vza
), solar azimuth angle (saa
), and view azimuth angle (vaa
) to the function calc_kgeo
. The function expects angles iexpressed as radians, but there is a helper function to convert from deg2rad (deg2rad
).
from s2brdf.kernels import deg2rad, calc_kgeo, calc_kvol
SZA = deg2rad(45)
SAA = deg2rad(180)
VZA = deg2rad(10)
VAA = deg2rad(0)
k_geo = calc_kgeo(SZA, VZA, SAA, VAA)
The function calc_kvol
will estimate volumetric kernel values:
k_vol = calc_kvol(SZA, VZA, SAA, VAA)
Each python source file has a corresponding test file in the tests
directory. The unit tests are set up using pytest
(install with pip install pytest
). To run all of the unit tests:
pytest
- Write the code for computing LiSparse (k_geo)
- Write the code (and test) for computing RossThick (k_vol)
- Normalise reflectance with coefficients from the litterature
- Put it all together in an Evalscript