PybsmPerturber#

class nrtk.impls.perturb_image.optical.PybsmPerturber(*, reflectance_range: ndarray[Any, Any] = array([0.05, 0.5]), pixel_conversion_mode: Literal['radiometric', 'minmax'] = 'radiometric', seed: int | None = None, is_static: bool = False, sensor_name: str = 'Sensor', D: float = 0.275, f: float = 4, p_x: float = 8e-06, p_y: float | None = None, opt_trans_wavelengths: ndarray[Any, Any] = array([5.0e-07, 6.6e-07]), optics_transmission: ndarray[Any, Any] | None = None, eta: float = 0.0, w_x: float | None = None, w_y: float | None = None, int_time: float = 1.0, n_tdi: float = 1.0, dark_current: float = 0.0, read_noise: float = 0.0, max_n: int = 100000000, bit_depth: float = 100.0, max_well_fill: float = 1.0, s_x: float = 0.0, s_y: float = 0.0, qe_wavelengths: ndarray[Any, Any] | None = None, qe: ndarray[Any, Any] | None = None, scenario_name: str = 'Scenario', ihaze: int = 1, altitude: float = 9000, ground_range: float = 0, aircraft_speed: float = 0.0, target_reflectance: float = 0.15, target_temperature: float = 295.0, background_reflectance: float = 0.07, background_temperature: float = 293.0, ha_wind_speed: float = 21.0, cn2_at_1m: float = 1.7e-14, interp: bool = True)#

Implements image perturbation using pyBSM sensor and scenario configurations.

The PybsmPerturber class applies realistic perturbations to images by leveraging pyBSM’s simulation functionalities. It takes in a sensor and scenario, along with other optional parameters, to simulate environmental effects on the image.

See https://pybsm.readthedocs.io/en/stable/explanation.html for image formation concepts and parameter details.

The simulation produces raw sensor measurements (photoelectron counts) that must be scaled to 0-255 to form the output image. pixel_conversion_mode selects how that scaling is done:

  • "radiometric" (default) uses a fixed mapping determined by the configured sensor and scenario. Darker or lower-contrast simulations produce darker or lower-contrast outputs — a dim or hazy scene stays dim in the output and may not use the full 0-255 range. Since the scale never changes from image to image, outputs can be compared directly across different sensor settings, across sweep steps, or between consecutive video frames.

  • "minmax" rescales each image individually so its darkest pixel becomes 0 and its brightest becomes 255. Every output looks bright and full-contrast, even when the simulated sensor would have produced a dim or washed-out image (the brightness/contrast part of the perturbation is removed from the output). Since each image gets its own scale, pixel values are not comparable between images, and video frames can visibly flicker. Choose "minmax" to visually inspect a single image or to mimic a camera pipeline that auto-adjusts gain/contrast on every frame before the model sees it.

If unsure, use the default "radiometric". It applies the same sensor-defined mapping to every output, so pixel values accurately represent the simulated sensor response.

For the conversion details (calibration inversion, clipping/saturation warnings, ADC fallback), see ImageSimulator.photoelectrons_to_pixels: Kitware/pybsm

Attributes:
reflectance_range (np.ndarray):

Default reflectance range for image simulation.

seed (int | None):

Random seed for reproducibility. None for non-deterministic behavior.

is_static (bool):

If True, recreates simulator after each call for consistent results.

Methods

from_config

Instantiate a new instance of this class given the configuration JSON-compliant dictionary encapsulating initialization arguments.

get_config

Get current configuration including perturber-specific parameters.

get_default_config

Retrieves the default configuration for PybsmPerturber instances.

get_impls

Discover plugins, skipping any entrypoints that fail to load.

get_type_string

Returns the fully qualified type string of the PerturbImage class or its subclass.

is_usable

Check whether this class is available for use.

perturb

Apply the OTF-based perturbation to the provided image.

__init__(*, reflectance_range: ndarray[Any, Any] = array([0.05, 0.5]), pixel_conversion_mode: Literal['radiometric', 'minmax'] = 'radiometric', seed: int | None = None, is_static: bool = False, sensor_name: str = 'Sensor', D: float = 0.275, f: float = 4, p_x: float = 8e-06, p_y: float | None = None, opt_trans_wavelengths: ndarray[Any, Any] = array([5.0e-07, 6.6e-07]), optics_transmission: ndarray[Any, Any] | None = None, eta: float = 0.0, w_x: float | None = None, w_y: float | None = None, int_time: float = 1.0, n_tdi: float = 1.0, dark_current: float = 0.0, read_noise: float = 0.0, max_n: int = 100000000, bit_depth: float = 100.0, max_well_fill: float = 1.0, s_x: float = 0.0, s_y: float = 0.0, qe_wavelengths: ndarray[Any, Any] | None = None, qe: ndarray[Any, Any] | None = None, scenario_name: str = 'Scenario', ihaze: int = 1, altitude: float = 9000, ground_range: float = 0, aircraft_speed: float = 0.0, target_reflectance: float = 0.15, target_temperature: float = 295.0, background_reflectance: float = 0.07, background_temperature: float = 293.0, ha_wind_speed: float = 21.0, cn2_at_1m: float = 1.7e-14, interp: bool = True) None#

Initializes the PybsmPerturber.

Args:
reflectance_range:

Array of reflectances that correspond to pixel values.

pixel_conversion_mode:

Defines how simulated photoelectrons are converted to uint8 pixels: “radiometric” (default) or “minmax”. See the class docstring for details on each mode.

seed:

Random seed for reproducible results. Defaults to None for non-deterministic behavior.

is_static:

If True and seed is provided, recreates simulator after each perturb call for consistent results across multiple calls (useful for video frame processing).

sensor_name:

name of the sensor

D:

effective aperture diameter (m)

f:

focal length (m)

p_x:

detector center-to-center spacings (pitch) in the x and y directions (meters); if p_y is not provided, it is assumed equal to p_x

opt_trans_wavelengths:

specifies the spectral bandpass of the camera (m); at minimum, specify a start and end wavelength

optics_transmission:

full system in-band optical transmission (unitless); do not include loss due to any telescope obscuration in this optical transmission array

eta:

relative linear obscuration (unitless); obscuration of the aperture commonly occurs within telescopes due to secondary mirror or spider supports

p_y:

detector center-to-center spacings (pitch) in the x and y directions (meters); if p_y is not provided, it is assumed equal to p_x

w_x:

detector width in the x and y directions (m); if set equal to p_x and p_y, this corresponds to an assumed full pixel fill factor. In general, w_x and w_y are less than p_x and p_y due to non-photo-sensitive area (typically transistors) around each pixel.

w_y:

detector width in the x and y directions (m); if set equal to p_x and p_y, this corresponds to an assumed full pixel fill factor. In general, w_x and w_y are less than p_x and p_y due to non-photo-sensitive area (typically transistors) around each pixel.

int_time:

maximum integration time (s)

qe:

quantum efficiency as a function of wavelength (e-/photon)

qe_wavelengths:

wavelengths corresponding to the array qe (m)

dark_current:

detector dark current (e-/s); dark current is the relatively small electric current that flows through photosensitive devices even when no photons enter the device

read_noise:

amount of noise generated by electronics as the charge present in the pixels

max_n:

detector electron well capacity (e-); the default 100 million initializes to a large number so that, in the absence of better information, it doesn’t affect outcomes

bit_depth:

resolution of the detector ADC in bits (unitless); default of 100 is a sufficiently large number so that in the absence of better information, it doesn’t affect outcomes

n_tdi:

number of TDI stages (unitless)

max_well_fill:

maximum amount of charge an individual pixel can hold before it becomes saturated

s_x:

root-mean-squared jitter amplitudes in the x direction (rad)

s_y:

root-mean-squared jitter amplitudes in the y direction (rad)

scenario_name:

name of the scenario

ihaze:

MODTRAN code for visibility, valid options are ihaze = 1 (Rural extinction with 23 km visibility) or ihaze = 2 (Rural extinction with 5 km visibility)

altitude:

sensor height above ground level in meters; the database includes the following altitude options: 2 32.55 75 150 225 500 meters, 1000 to 12000 in 1000 meter steps, and 14000 to 20000 in 2000 meter steps, 24500; exact database values are only required when interp is False

ground_range:

projection of line of sight between the camera and target along on the ground in meters; the distance between the target and the camera is given by sqrt(altitude^2 + ground_range^2). The following ground ranges are included in the database at each altitude until the ground range exceeds the distance to the spherical earth horizon: 0 100 500 1000 to 20000 in 1000 meter steps, 22000 to 80000 in 2000 m steps, and 85000 to 300000 in 5000 meter steps. Exact database values are only required when interp is False.

aircraft_speed:

ground speed of the aircraft (m/s)

target_reflectance:

object reflectance (unitless); the default 0.15 is the giqe standard

target_temperature:

object temperature (Kelvin); 282 K is used for GIQE calculation

background_reflectance:

background reflectance (unitless)

background_temperature:

background temperature (Kelvin); 280 K used for GIQE calculation

ha_wind_speed:

the high altitude wind speed (m/s) used to calculate the turbulence profile; the default, 21.0, is the HV 5/7 profile value

cn2_at_1m:

the refractive index structure parameter “near the ground” (e.g. at h = 1 m) used to calculate the turbulence profile; the default, 1.7e-14, is the HV 5/7 profile value

interp:

A flag to indicate whether atmospheric interpolation should be used. When True, altitude and ground_range can be any value within the database bounds (the atmosphere is bilinearly interpolated). Exact database values are only required when False. (Defaults to True).

Raises:
ValueError:

If reflectance_range length != 2

ValueError:

If reflectance_range not strictly ascending

ValueError:

If pixel_conversion_mode is not “radiometric” or “minmax”

__repr__() str#

Returns a representation of the perturber including sensor and scenario names.

__str__() str#

Returns a string representation combining sensor and scenario names.

get_config() dict[str, Any]#

Get current configuration including perturber-specific parameters.

classmethod get_default_config() dict[str, Any]#

Retrieves the default configuration for PybsmPerturber instances.