22 - Four-component classification¶
FourComponentImager classifies what the sensor sees in each pixel into four classes: sunlit leaves, shaded leaves, sunlit soil and shaded soil, and gives the visible area of each. The four components are widely used for unmixing thermal pixels, retrieving component temperatures and modelling directional brightness temperature.
How the classification works¶
Each pixel sends a number of viewing rays. Where a ray reaches the scene, two questions are asked:
- Did it land on the ground or on a leaf?
- Can that point see the sun? A ray is sent towards the sun; if it is blocked, the point is shaded.
Combining the answers gives four classes. Each pixel is labelled with its majority class, and the fraction of each class is kept as well, so the information in mixed pixels is not lost.
| Label | Component | Meaning |
|---|---|---|
| 0 | background | Hit nothing |
| 1 | sunlit_soil | Sunlit soil |
| 2 | sunlit_leaf | Sunlit leaves |
| 3 | shaded_soil | Shaded soil |
| 4 | shaded_leaf | Shaded leaves |
For statistical vegetation, a ray counts as a leaf as soon as it enters the canopy boundary.
Example¶
import less
scene = less.Scene()
scene.size = 30.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.15))
scene.illumination = less.Illumination(
source=less.Sun(zenith=35, azimuth=180), atmosphere=less.NoAtmosphere())
maize = less.Object("maize", mesh=less.asset_path("maize.obj"))
maize.set_property(less.Lambertian(reflectance=0.45, transmittance=0.05))
scene.add(maize, positions=[(x, y, 0.0) for x in range(6, 25, 3) for y in range(6, 25, 3)])
sensor = less.FourComponentImager(
less.Orthographic(image_size=256, extent=20.0, center=(15.0, 15.0)),
num_samples=64)
product = scene.simulate(sensor)
print(product.summary())
product.save_classification("four_component.png")
Four-component classification uses orthographic projection only, so that the component areas have a clear geometric meaning. num_samples is the number of viewing rays per pixel and sets the precision of the fractions.
Results¶
| Attribute or method | Shape | Meaning |
|---|---|---|
product.labels |
(rows, columns), uint8 | Majority class of each pixel |
product.fractions |
(rows, columns, 4) | Fractions of the four classes: sunlit soil, sunlit leaves, shaded soil, shaded leaves |
product.pixel_area_m2 |
number | Ground area of one pixel |
product.summary() |
dictionary | Visible area of each component (m²) |
product.area(name) |
number | Visible area of one component |
product.save_classification(path) |
— | Saves a colour classification map |
Component areas are summed from the fractions:
where f is the fraction of the component in the pixel. The four areas add up to the imaged area, 20 m × 20 m = 400 m² here, which is a useful check:
areas = product.summary()
print(sum(areas[name] for name in ("sunlit_soil", "sunlit_leaf", "shaded_soil", "shaded_leaf")))
If the imaged area extends beyond the ground, the difference shows up as background.
Periodic scenes¶
With periodic boundaries, both viewing rays and shadow rays continue across the scene edges. When the sun is low, long shadows can come back from the other side of the scene, so the shaded soil area grows noticeably while the total soil area stays the same: