18 - Sensor overview¶
A sensor describes from where, in what way and in which bands the scene is observed. This chapter covers what all sensors have in common: projections, bands, sampling and results. The following chapters introduce the optical, radiation-measurement, LiDAR, thermal, fluorescence and microwave sensors.
What an imaging sensor consists of¶
An imaging sensor combines a projection and a set of bands:
import less
sensor = less.OpticalImager(
less.Orthographic(image_size=128), # projection
bands=[650, 550, 450], # bands (nm)
quality=32, # samples per pixel
)
The same projections are used for optical, thermal and fluorescence imaging.
Projections¶
Orthographic¶
All viewing rays are parallel and the pixel grid is fixed on a horizontal reference plane above the ground. The result is a map-like image with north up and east to the right:
nadir = less.Orthographic(image_size=256) # 256 × 256 pixels
fine = less.Orthographic(resolution=0.1) # 0.1 m per pixel
subset = less.Orthographic(image_size=128, extent=20, center=(25, 25))
oblique = less.Orthographic(image_size=128, view_zenith=30, view_azimuth=120)
| Parameter | Meaning |
|---|---|
image_size |
Number of pixels, an integer or (width, height) |
resolution |
Ground resolution (m), instead of image_size |
extent |
Imaged area (m), the whole scene by default |
center |
Image centre (east, south), the scene centre by default |
view_zenith, view_azimuth |
Viewing zenith and azimuth for oblique views |
terrain_following |
On uneven terrain, each pixel corresponds to the ground below it |
For oblique views the horizontal plane holding the pixel grid is set by scene.measurement_plane: by default ("auto") it is the top of the scene, which suits canopy reflectance; with 0 it is the ground, and objects are displaced in the image along the viewing direction according to their height:
Perspective¶
A normal camera, where nearer objects look larger:
camera = less.Perspective(resolution=512, fov=35,
position=(25, 60, 20), # camera position
target=(25, 25, 5)) # point the camera looks at
fov is the field of view in degrees.
Fisheye¶
Hemispherical views, often used to simulate hemispherical canopy photographs:
orientation="up" looks at the sky and "down" at the ground; projection can be "equisolid" (equal solid angle, default), "equidistant", "orthographic" or "stereographic".
Pushbroom¶
Satellite or airborne pushbroom imaging, see chapter 20.
Sampling method¶
Choose a sampling policy for the scene:
scene.sampler = less.Sampler("sobol", seed=17)
image = scene.simulate(less.OpticalImager(
less.Orthographic(image_size=128), bands=[550, 850], quality=256))
Supported imaging and photon-emission workflows use "sobol" by default.
"independent" selects independent random sampling; "stratified" uses
stratification. "sobol" uses randomized low-discrepancy points and works best
with power-of-two sample counts. The sensor still sets quality or num_photons;
the sampler determines how these samples are distributed.
Low-discrepancy modes apply to within-pixel locations in optical, thermal,
fluorescence and passive microwave images, and initial photon emission for optical
BRF, irradiance maps and forward radiation fields. Subsequent scattering uses
independent random samples. Other workflows do not yet accept low-discrepancy modes.
LiDAR, active microwave and processes such as energy balance retain their existing
sampling schemes. Optical standard_error requests use independent sampling when
no sampling method is specified, as required by that estimator. To reproduce
independent random streams, set scene.sampler = less.Sampler("independent").
seed=None inherits the workflow's existing seed. An explicit integer also controls
transport random streams in workflows supporting this setting. Repeat simulations
with different seeds and sample counts to assess stability: low-discrepancy sampling
does not improve convergence in every scene. Set scene.sampler = None to restore
the defaults.
For microwave images without separate projection sampling settings, the sensor's
seed also controls the Sobol digital shift. An explicit scene seed takes priority.
Sampling within pixels¶
Projection settings can instead change only within-pixel locations while preserving
transport random streams. When scene.sampler is set, its method takes priority
over projection settings; an explicit scene seed also takes priority.
When pixels contain a mixture of leaves, gaps or shadows, more evenly distributed sample locations may improve convergence:
projection = less.Orthographic(
image_size=128, pixel_sampling="sobol", sampling_seed=17)
sensor = less.OpticalImager(projection, bands=[550, 850], quality=256)
pixel_sampling=None follows the defaults above. Explicit "independent" selects
independent random samples.
"stratified" jitters one sample within each equal-area cell and accepts any
positive integer quality. "sobol" uses digitally shifted Sobol points; powers of two
are recommended for quality. These options also apply to thermal, fluorescence
and passive microwave images and to other passive imaging projections.
Active microwave continues to use its sensor's seed.
sampling_seed changes only the locations within pixels, leaving subsequent
transport random inputs unchanged. Repeating with different seeds assesses pixel-quadrature
variability, rather than uncertainty in the entire transport process.
Stratified and Sobol samples are correlated, so the optical standard_error
product requires independent sampling. Convergence still depends on scene
boundaries and scattering; check stability as quality increases.
Bands¶
rgb = [650, 550, 450] # list of band centres (nm)
sentinel = less.Sentinel2A() # Sentinel-2A spectral response functions
landsat = less.Landsat8_OLI() # Landsat 8 OLI
hyperspectral = less.Hyperspectral(start=400, stop=1000, step=10)
With a list of band centres, each band is computed at a single wavelength. With a satellite instrument, LESS samples each band across its spectral response and weights the samples; spectral_resolution is the sampling interval (nm):
s2 = less.OpticalImager(less.Orthographic(image_size=64), bands=less.Sentinel2A(),
spectral_resolution=5, quality=16)
Bands in the result keep the order in which they were given.
Sampling¶
quality is the number of samples per pixel. Monte Carlo results contain random noise, roughly inversely proportional to the square root of the number of samples: four times as many samples halves the noise. Check a scene with small values, increase them for final results, and compare results at different sample counts to make sure they are stable.
| quality | Use |
|---|---|
| 16–64 | Previews |
| 128–256 | General analysis |
| 512 and above | Quantitative work |
Non-imaging sensors have their own sampling parameters, such as num_photons for multi-angle reflectance.
Sensors at a glance¶
| Sensor | Result | Chapter |
|---|---|---|
OpticalImager |
Optical images | 19, 20 |
BRFSensor |
Multi-angle reflectance | 21 |
IrradianceMapSensor |
Upwelling and downwelling irradiance maps | 23 |
IrradianceRadiometer |
Point irradiance | 24 |
LiDARSurvey |
Point clouds, waveforms | 25 |
ThermalImager |
Thermal images | 26 |
SIFImager |
Fluorescence images | 27 |
RadarScatterometer |
Backscattering coefficients | 29 |
MicrowaveRadiometer |
Brightness temperatures | 30 |
Results¶
scene.size = 50.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.2))
scene.illumination = less.Illumination(
source=less.Sun(zenith=30, azimuth=150), atmosphere=less.NoAtmosphere())
image = scene.simulate(sensor)
print(image.data.shape) # (rows, columns, bands)
image.save("image.png") # for viewing
image.save("image.tif") # keeps the values
image.show() # display with matplotlib
Image values are spectral radiance (W m⁻² sr⁻¹ nm⁻¹); image.to_brf() converts them to reflectance factor.