.. _abbe's diffraction limit: https://www.microscopyu.com/techniques/super-resolution/the-diffraction-barrier-in-optical-microscopy
##########################
Image Formation Concepts
##########################
pyBSM replicates image formation based on the physical and electronic characteristics of the sensor and scene. The pyBSM
image formation chain consists of 4 separate components:
- **3D World**: Physical geometry and materials of the scene
- **Atmosphere**: Scattering, absorption, and turbulence
- **Optics**: Image formation through lenses and apertures
- **Sensor and Electronics**: Detection, digitization, and noise modeling
These components are illustrated below:
.. figure:: figures/overall_pipeline.png
Figure 1: This modular structure underpins all simulations in pyBSM.
Ultimately, pyBSM bases its models and simulations around this image formation pipeline.
*****************************************************************
Point-Spread Function (PSF) and Optical Transfer Function (OTF)
*****************************************************************
pyBSM is built on the principle of *translation-invariant systems*, or that the image process can be described by a set
of functions that degrade the ideal image scenario. Fundamental to this principle is the simulation of Point-Spread
Functions (PSFs) and Optical Transfer Functions (OTFs), which describe how an ideal scene is transformed as light
reaches the sensor. A PSF is a function that is convoluted with the scene to create the degradations, while at OTF is
the same thing except in the frequency domain (i.e. an OTF is the Fourier transform of a PSF). An OTF which has large
values for certain frequencies will faithfully replicate those frequencies on the sensor, while low values would
diminish or remove those frequencies entirely. For example, a diffraction-based OTF would have low values for
frequencies above `Abbe's diffraction limit`_, since the lens cannot reconstruct these frequencies. This OTF would also
therefore change based on the optics used, as a larger numerical aperture would afford a larger Abbe's diffraction
limit. A perfect and ideal OTF would be equal to 1 for all frequency values.
.. figure:: figures/psf_example.png
Figure 2: Description of PSFs
In pyBSM, the overall OTF and PSF of the system is called the "Composite System PSF", and is composed of a combination
of the PSFs from all the separate components:
- Turbulence
- Jitter and Drift
- Diffraction
- Defocus
- Wavefront
- Charge Diffusion
- Detector
.. figure:: figures/psf_list.png
Figure 3: Depiction of all PSFs in pyBSM
It is important to note that each PSF degrades the ideal image and cannot enhance resolution. However, the interplay and
combination of many PSFs together is complex. Some examples of these OTFs are in
`NRTK/docs/examples/otf_visualization.ipynb`_
******************
Image Simulation
******************
pyBSM allows the user to simulate different environmental or sensor effects for a given reference image and therefore
simulate new OTFs. Some practical examples include if the user wants to increase the sensor noise, change the distance
from the sensor to target, increase environmental wind speed, or change the aperature size of the lens.
To simulate the effects of these variables, pyBSM simulators are composed of three elementary classes:
- **Sensor**: Defines the physical and electronic characteristics of the sensor and optics, including pixel pitch,
focal length, aperture diameter, sensor noise, and spectral response.
- **Scenario**: Captures details about the environment and scene, such as the observer's altitude and speed,
atmospheric conditions, and the reflectance and temperature of the target.
- **Reference Image**: Represents the baseline or *ideal image* from which degradations are simulated. It includes
pixel intensity values, ground sampling distance (GSD), and optionally a mapping between pixel values and
reflectance.
.. figure:: figures/simulator_pipeline.png
Figure 4: Depiction of simulator pipeline
An example notebook simulation is included in `NRTK/docs/examples/pybsm/pybsm_test.ipynb`_
Main Sensor Variables
=====================
The sensor class has the most variables in the simulator. If these are unknown or unspecified, they can be estimated via
the "estimate_capture_parameters" function in the ref_image class, but oftentimes they can be determined by the camera's
datasheet.
Overall, the main variables of interest can be separated into several categories:
**Pixel Size Parameters**: These include changes in the image due to the geometrical pixel sizes
- ``p_x``, ``p_y``: center-to-center spacing between pixels in the x/y directions (meters). This is also known as
``pixel_pitch``, and this will change the resolution of the resulting image. Note if p_y is not provided, it is
assumed to be equal ``p_x```` (``p_x`` *is required,* ``p_y`` *can be None*).
- ``w_x``, ``w_y``: actual width of the photoreceptive component of the pixel (meters). Note that this should always be
less than ``p_x`` , ``p_y``, since this describes the "fill factor."" If ``w_x`` = ``p_x`` and ``w_y`` = ``p_y``,
fill factor is 1 and the entire pixel is photoreceptive. If ``w_x`` = 1/2 * ``p_x`` and ``w_y`` = 1/2 * ``p_y``, then
the fill factor is .25 since the photoreceptive component only comprises 25% of the entire sensor area (*default
None*).
**Lens and Optics** These parameters determine the projection of the scene onto the sensor:
- ``f``: focal length of the lens (meters). A large focal length typically has a narrower field-of-view with compressed
depth of the scene, while a smaller focal length has a wider field-of-view with exaggerated and distorted
perspectives (*required*).
- ``D``: effective aperture diameter of the lens (meters). This is related to the f-number (f#) of the lens, which
defines the how much light is reaching the sensor alongside the depth of field and diffraction. A small aperture
(i.e. small f#) results in less light and shallower depth-of-field but less diffraction and sharper images, while a
large aperture (i.e. large f#) results in more light and deeper depth-of-field but less sharp images (*required*).
Here is a depiction of the pixel size and optics variables:
.. figure:: figures/sensor_and_optics_vars.png
Figure 5: Depiction of sensor variables
**Spectral Response** These parameters define how the sensor responds to different wavelengths of light:
- ``qewavelengths``, ``qe``: the detector quantum efficiency (QE) of the corresponding wavelengths (microns). QE
defines what percentage of the incoming photons are converted to electrons by the sensor, where sensor which has a
large QE with respect to a specific wavelength will capture that color more strongly than it would to one with a
smaller QE. Note that QE cannot be greater than 1, as 1 is perfect efficiency. Most sensors will have the QE
published. For a generic, high quality back-illuminated (BI) silicon sensor the values would be: qewavelengths:
\[0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1\] (*default is opt_trans_wavelengths*)
- ``qe``: [0.05, 0.6, 0.75, 0.85, 0.85, 0.75, 0.5, 0.2, 0] (*default ones*).
- ``opt_trans_wavelengths``: specifies the start and end wavelengths the camera captures (meters). This is the
"spectral bandpass."" Unless the optics of the camera are set specifically to isolate certain colors, this can be set
as wide as the quantum efficiency, so the previous example would be 0.3e-6 to 1.1e-6 (*required*).
**Noise and Signal Quality**: These capture the noise and signal-to-noise (SNR) characteristics of the camera.
- ``int_time``: maximum integration time of the sensor, or how long it converts photons to electrons (seconds). Also
known as "exposure time." We use the term "maximum" since the image will be clipped depending on the monitor well
fill percentage (i.e. max_n) (*default 1.0*).
- ``bit_depth``: How many bits are used to represent the values in each pixel (bits). Standard 0-255 images are 8-bit,
while larger bits capture more signal and a larger dynamic range of values (*default 100.0*).
- ``read_noise``: electron noise created in reading out the pixels (root-mean squared electrons). This is especially
problematic in dark scenes where the captured signal is low in which the read noise can overwhelm it (*default 0.0*).
- ``dark_current``: the small amount of electrons going through each pixel even when no photons are entering (electrons
per second). Dark current is what typically overwhelms low-light images (*default 0.0*).
- ``max_n``: the detector electron well capacity (electrons). This is the maximum amount of electrons that can be
captured by each pixel in the integration time (*default is 100e6*).
- ``optics_transmission``: full system, in-band optical transmission (unitless). Not counting other qualities, how much
of received light is captured by camera where the minimum is 0 and maximum is 1 (*default ones*).
- ``s_x``, ``s_y``: root-mean-squared jitter amplitudes in the x and y directions (radians). These correspond to small,
rapid motions that could come from internal vibrations or camera shake (*default 0.0*).
- ``da_x``, ``da_y``: line-of-sight angular drift rate during one integration time in the x and y directions
(radians/second). This relates to how the sensor's viewing direction drifts during an exposure time, such as would be
from a moving aircraft. This would result in a blurred image in the direction of movement (*default 0.0*).
Some more uncommon variables not explained, but more information can be found at :ref:`sensor`
**Example Sensor Implementation Variables**
`Here `_ is an example of sensor variables from the Sony IMX455 CMOS
sensor with the Canon EF 200mm f/2.8L II USM `lens
`_, which result in the following
sensor variables:
*Pixel and Optics*
- ``p_x`` = ``p_y`` =3.76e-6
- ``w_x`` = ``w_y`` = ``p_x`` (not given, but should be high because of BSI architecture)
- ``f`` =35e-3
- ``D`` > 32e-3
*Noise and Signal Quality*
- 40e-6 < ``int_time`` < 3600
- ``bit_depth`` =16
- ``dark_current`` =0.0022
- 1.0 < ``read_noise`` < 3.7
- ``max_n`` = 51e3
- ``s_x``, ``s_y`` depend on aircraft scenario
- ``da_x``, ``da_y`` unclear
*Spectral Response* (based on `this document
`_)
- ``qewavelengths`` =[496e-9, 656.3e-9, 671.6e-9, 889e-9] (could use more wavelengths)
- ``qe`` =[0.91, 0.81, 0.79, 0.40] (could use more wavelengths)
- ``opt_trans_wavelengths`` [496e-9, 889e-9]
*Other Variables*
- ``pix_values``, ``refl_values`` are approximately linear to each other, based on
how the electron well fills up with regards to exposure time
(`document `_). However, this
might change based on specific capture parameters.
Main Scenario Variables
=======================
These variables change qualities about the imaging scenario, mainly concerned with the atmospheric effects but also
about some of the background and object qualities. These would affect the turbulence and SNR profiles.
- ``ihaze``: the haze index of the scenario (MODTRAN code for visibility). For example, ihaze = 1 corresponds to rural
extinction with 23 km visibility while ihaze = 2 corresponds to rural extinction with 5 km visibility (*required*).
- ``altitude``: height of sensor above ground level (meters). Higher sensors will be more affected by atmospheric
effects (*required*).
- ``ground_range``: projection of line-of-sight between the camera and the target along the ground (meters). The total
distance between the target and the camera is given by sqrt(``altitude``\^2 + ``ground_range``\^2) (*required*).
- ``aircraft_speed``: ground speed of the aircraft (meters/second) (default 0).
- ``target_reflectance``, ``background_reflectance``: reflectance values of the object and background (unitless).
Defines the brightness values received by the sensor (*default 0.15 and 0.07*).
- ``target_temperature``, ``background_temperature``: temperature of the object and background (Kelvin). Used in SNR
calculations (*default is 282 and 280*)
- ``ha_wind_speed``: the high altitude wind speed (meters/second). This is used to calculate the turbulence profile
(*default 21.0*).
- ``cn2_at_1m``: the refractive index structure parameter near the ground (unitless). It is used to calculate the
turbluence profile (*default 1.7e-14*).
- ``interp``: a flag used to indicate whether atmospheric interpolation should be used (*default False*)
Here is an example depiction of the scenario variables:
.. figure:: figures/scenario_vars.png
Figure 6: Depiction of scenario variables
More information is found at :ref:`scenario`
Main Reference Image Variables
==============================
These variables contain information about the image target and the actual pixel values. An important function in
ref_image is "estimate_capture_parameters" which can be used to estimate the camera sensor parameters used to capture
the image given some scenario parameters. It is important to remember that the reference image is the ``ideal`` image,
in that its quality will not be improved upon in the simulation but degraded or altered based on the parameters.
Key parameters include:
- ``img``: the reference image data (array). This contains the pixel values of the image (*required*).
- ``gsd``: the reference isotropic ground sampling distance per pixel (meters). This is the spatial sampling of the
image, where each pixel in the image is assumed to be a gsd x gsd square on the world surface (*required*).
- ``pix_values/refl_values``: This is an optional parameter which associates pixel count values (i.e. 0 to 255) to
scene reflectance values (i.e. 0 to 1), where pix_values and refl_values are equal-length arrays of the pixel values
which correspond to reflectance values. This is important to set if you want to convert the pixel values to raw image
values captured by the sensor, and it is important to take the non-linearities of the sensor encoding into account.
Note that pixel values not shared will be linearly interpolated from the given values (*default none, need to set
both if using them*).
For some examples on how to calculate the ``pix_values/refl_values`` and the ``gsd``, please visit the documentation in
`pybsm/docs/useful_calculations.rst`_.
More information is found at :ref:`RefImage`
****************************************
Optical Transfer Function (OTF) Models
****************************************
The main OTFs to consider are:
- **circular_aperture_OTF/_with_defocus**: Diffraction from optics and aperture (``D`` , ``f``)
- **detector_OTF/_with_aggregation**: Detector spatial integration effects, particularly important if fill factor is
not 100% (``p_x``, ``p_y``, ``w_x``, ``w_y``, ``f``, ``n`` [pixels to aggregate])
- **drift_OTF**: Line-of-sight angular blur (``da_x``, ``da_y``, ``int_time``)
- **filter_OTF**: Custom filters (e.g., sharpening) (``p_x``, ``p_y``, ``f``)
- **gaussian_OTF**: Generic unmodeled Gaussian blur (``Misc``)
- **jitter_OTF**: Blur from high-frequency camera jitters (``s_x``, ``s_y``)
- **polychromatic_turbulence_OTF/turbluence_OTF**: Atmospheric effects (``opt_trans_wavelengths``, ``altitude``,
``ground_range``, ``D``, ``int_time``, ``aircraft_speed``, ``ha_wind_speed``, ``cn_at_1m``)
There are some more specialized OTFs contained in :mod:`~pybsm.otf.functional`. These include ``cte_OTF`` (CCD charge
transfer efficiency losses), ``diffusion_OTF`` (CCD minority carrier diffusion), ``tdi_OTF`` (time-delay-integration),
``wavefront_OTF`` (wavefront effects).
.. _nrtk/docs/examples/otf_visualization.ipynb: https://github.com/Kitware/nrtk/blob/main/docs/examples/otf_visualization.ipynb
.. _nrtk/docs/examples/pybsm/pybsm_test.ipynb: https://github.com/Kitware/nrtk/blob/main/docs/examples/pybsm/pybsm_test.ipynb