The SkyBathy tool implements a physics-based approach, solved statistically, to derive bathymetry (water depth) from multispectral satellite imagery. This method is a generalized implementation of the classic Lyzenga algorithm (1978, 2006).
Unlike pure analytical methods, which require precise field measurements of water optical properties (attenuation coefficients \(K_d\)) and bottom reflectance (\(R_b\)), this method estimates these parameters directly from the data by using a regression between pixel values and known depth points (from the uploaded CSV).
The theory is grounded in the Beer-Lambert Law, which describes the exponential attenuation of light as it travels through water. The radiance measured by the satellite (\(L_{sat}\)) in a visible band can be simplified as:
Where:
To solve the equation for depth \(z\) using linear statistical techniques, we must remove the exponential component.
We subtract \(L_{\infty}\) from both sides to isolate the signal coming from the water column and the bottom. In the code, \(L_{\infty}\) is automatically calculated as the average of the darkest pixels (5th percentile) within the water mask.
By applying the natural logarithm (\(\ln\)) to both sides, the equation becomes linear with respect to \(z\):
Rearranging to isolate \(z\):
In a pure theoretical model, we would need to know the physical values of \(K\) and the bottom reflectance. However, these vary spatially and are difficult to measure without expensive equipment. The approach implemented in SkyBathy bypasses this problem by assuming the equation above can be written as a Multiple Linear Regression Model.
Instead of solving for a single band, we use \(N\) visible bands (Blue, Green, Red) to compensate for variations in bottom type (e.g., sand vs. seagrass). The final equation becomes:
Where:
Unlike the physical method, we do not fix \(K_d\) or \(R_b\). Instead:
These coefficients are determined by solving a system of linear equations (Ordinary Least Squares) using the control points provided in your CSV file.
In the file skybathy_derived.html, the process occurs in the solveLyzenga() function following these steps:
computeDeepWaterRadiance() finds pixels where water is deep (minimum signal) and calculates the subtraction value for each band.multipleLinearRegression) to find the coefficient vector \(\beta\) (containing \(a_0, a_1, a_2\)).