Robust binarization without parameter tuning.
ootb_bin(caim, z, a, m, parallel = TRUE)Logical terra::SpatRaster (TRUE for sky, FALSE for non-sky)
with the same number of rows and columns as caim.
numeric terra::SpatRaster with three layers named
"Red", "Green", and "Blue". Digital numbers should be linearly
related to radiance. See read_caim_raw() for details.
terra::SpatRaster generated with zenith_image().
terra::SpatRaster generated with azimuth_image().
logical terra::SpatRaster with one layer. A binary mask with
TRUE for selected pixels.
logical vector of length one. If TRUE, operations are
executed in parallel.
Runs a predefined pipeline that incrementally refines a binary sky mask by combining gradient-based enhancement, local thresholding, polar segmentation, and a spectral index sensitive to sunlit canopy.
Enhancement. Compute complementary gradients with
complementary_gradients() and build an enhancer that mixes the
strongest complementary response with the blue band:
mem <- mean(normalize_minmax(max(yellow_blue, red_cyan)), normalize_minmax(Blue^(1/2.2))).
Gamma correction (see invert_gamma_correction()) is applied to the blue band to
reduce sky brightness variability.
Local thresholding. Apply apply_by_direction() on mem
with method = "thr_isodata" to obtain an initial binary mask. Local
thresholding is required because background non-uniformity remains in the
enhanced image.
Cleanup. Remove isolated pixels and apply a one-pixel binary
dilation. This compensates small artifacts produced by band misalignment
resulting from the radiometric-first policy of read_caim_raw().
Polar quadtree segmentation. Segment this preclassification of
sky and non-sky pixels with polar_qtree() parameterized to yield circular
trapezoids never smaller than \(3 \times 3\) degrees and to minimize
segments with mixed classes.
Object-based image analysis.
Keep segments that contain between 10 and 90 percent of sky pixels.
For each kept segment, estimate a local sky reference as the maximum blue
value, use it to normalize per segment
(ratio <- Blue / sky_segment_max), interpret the normalization as the degree
of membership to the sky class, and then defuzzify with a fixed threshold
0.5.
Blue–Red Index (BRI). Compute $$\mathrm{BRI} = \frac{B - R}{B + R}$$ where \(B\) and \(R\) are blue and red digital numbers. BRI decreases on sunlit canopy because direct sunlight is warmer than diffuse skylight. Use a scene-adaptive threshold given by the median BRI over the current non-sky region to flip misclassified sky pixels to non-sky.
Zenith mask. Apply the final zenith-angle gate (e.g., keep \(\theta_z \le 88^\circ\)).
if (FALSE) {
caim <- read_caim()
r <- caim$Blue
z <- zenith_image(ncol(caim), lens())
a <- azimuth_image(z)
m <- !is.na(z)
bin <- ootb_bin(caim, z, a, m)
plot(bin)
}
Run the code above in your browser using DataLab