pyoptics.processing¶
Module that defines image processing classes.
The following processors are defined:
Scaler: scale images to a given peak, mean or total value of the field strength or of the intensity
CameraNoiser: apply a camera noise model (Gaussian, Poisson photon noise or a full linear camera model following EMVA 1288)
Shifter: shift images
Centerer: center images on their intensity centroid
All processors are callables that accept a single image (2d array) or an
image stack (3d array, the last index numbering the images). Images may be
complex valued fields E or (real) intensities. The intensity of a field is
taken as |E|**2 throughout this module, without the prefactor n/(2 Z_0) of
utils.I().
References¶
EMVA Standard 1288, “Standard for Characterization of Image Sensors and Cameras”, Release 4.0, European Machine Vision Association (2021).
Janesick, “Photon Transfer”, SPIE Press (2007).
Classes
Processor that applies a camera noise model to images. |
|
Processor that centers images on their intensity centroid. |
|
Base class for all image processor. |
|
Processor that scales an image or an image stack. |
|
Processor that shifts images. |
- class pyoptics.processing.ImageProcessor[source]¶
Bases:
objectBase class for all image processor.
All derived classes need to
have a constructor that correctly sets the processor up
implement
process_single_image(self, image, *params)
- class pyoptics.processing.Scaler(value, measure='peak', quantity='intensity', image_type='auto', per_image=True, pixel_area=1.0)[source]¶
Bases:
ImageProcessorProcessor that scales an image or an image stack.
The image is multiplied by a real factor such that a chosen measure of either the field strength
|E|or the intensity I =|E|**2equals a given value. Images may be fields or intensities: a field is multiplied by c, an intensity by c**2 if the field strength is to be scaled by c.- Parameters:
- valuefloat
Target value of the measure.
- measurestr, optional
“peak” (maximum), “mean” or “total”. For the intensity, “total” is the power sum(I)*pixel_area; for the field strength it is the norm
sqrt(sum(|E|**2)*pixel_area), so that scaling the field to a total of sqrt(P) is the same as scaling the intensity to a total of P.- quantitystr, optional
“intensity” or “field”: the quantity whose measure is set to value.
- image_typestr, optional
What the input images are: “field”, “intensity” or “auto” (complex images are fields, real images are intensities). Use “field” for real valued amplitudes.
- per_imagebool, optional
If True (default), every image of a stack is scaled individually. If False, one common factor is used for the stack so that relative intensities are preserved; the measure is then taken over the whole stack (global peak, global mean, total averaged over the images).
- pixel_areafloat, optional
Pixel area dx*dy used for measure=”total”.
Examples
>>> to_photons = Scaler(1000.0) # peak intensity: 1000 photons per pixel >>> unit_power = Scaler(1.0, measure="total", pixel_area=dx*dy)
- class pyoptics.processing.CameraNoiser(model='camera', sigma=0.0, relative=False, quantum_efficiency=1.0, dark_current=0.0, exposure_time=1.0, read_noise=0.0, full_well=None, gain=1.0, offset=0.0, bit_depth=None, prnu=0.0, dsnu=0.0, rng=None)[source]¶
Bases:
ImageProcessorProcessor that applies a camera noise model to images.
Three models are available:
“gaussian”: additive white Gaussian noise of standard deviation sigma (absolute, or relative to the image’s peak if relative=True). The image may be an intensity or a field; for a complex field, independent noise is added to the real and imaginary parts.
“poisson”: photon shot noise only. The image is the expected number of photons per pixel; the result is a Poisson distributed photon count.
“camera”: linear camera model following the EMVA 1288 standard. The image is the expected number of photons per pixel and exposure. The chain is
photons --(Poisson, quantum_efficiency)--> photo electrons + dark electrons (Poisson, dark_current*exposure_time) -> clipped at full_well * (1 + PRNU pattern) + read noise (Gaussian, read_noise) + DSNU pattern * gain + offset -> rounded and clipped to [0, 2**bit_depth - 1] (if bit_depth)
The result is in digital numbers (DN). The fixed pattern noise (PRNU, DSNU) is drawn once per image shape and then stays the same for all images processed by this noiser, like on a real sensor.
For the “poisson” and “camera” models, fields are converted to intensities
|E|**2first. Use a Scaler to bring images to photon numbers, e.g. Scaler(1000.0) for a peak of 1000 photons per pixel.- Parameters:
- modelstr, optional
“gaussian”, “poisson” or “camera”.
- sigmafloat, optional
Standard deviation of the “gaussian” model.
- relativebool, optional
If True, sigma is relative to the peak of each image (“gaussian” model only).
- quantum_efficiencyfloat, optional
Fraction of photons converted to electrons.
- dark_currentfloat, optional
Dark current in electrons per pixel and unit time.
- exposure_timefloat, optional
Exposure time (in the time unit of dark_current).
- read_noisefloat, optional
Read noise (temporal dark noise) in electrons rms.
- full_wellfloat, optional
Full well capacity in electrons; None means no saturation.
- gainfloat, optional
System gain in DN per electron (K in EMVA 1288).
- offsetfloat, optional
Dark offset (bias) in DN.
- bit_depthint, optional
ADC resolution in bits; None means no quantization or clipping.
- prnufloat, optional
Photo response non-uniformity: relative rms gain variation from pixel to pixel.
- dsnufloat, optional
Dark signal non-uniformity: rms offset variation from pixel to pixel in electrons.
- rngint, numpy.random.Generator or None, optional
Seed or random number generator for reproducible noise.
- fixed_pattern(shape)[source]¶
Return the fixed pattern noise (relative gain deviation, offset deviation in electrons) for images of the given shape.
- mean_signal(photons)[source]¶
Expected output of the “camera” model in DN for the given expected photon numbers, ignoring fixed pattern noise, saturation and quantization.
- class pyoptics.processing.Shifter(delta_x, delta_y, x, y)[source]¶
Bases:
ImageProcessorProcessor that shifts images.
The shift uses the Fourier shift theorem: it is periodic (content leaving the grid on one side enters it on the other side) and works for subpixel shifts. For real images the real part of the result is returned.
- class pyoptics.processing.Centerer(x, y, x0=0.0, y0=0.0, threshold=0.0, per_image=True, iterations=1)[source]¶
Bases:
ShifterProcessor that centers images on their intensity centroid.
Every image is shifted (with the periodic Fourier shift of Shifter) such that its intensity centroid (center of mass, see utils.center_of_mass()) lies at (x0, y0). Fields are centered on the centroid of
|E|**2.- Parameters:
- x, yarrays
1d coordinate grids of the images (image shape (len(y), len(x))).
- x0, y0float, optional
Target position of the centroid; default is the origin.
- thresholdfloat, optional
Pixels with an intensity below threshold times the image’s peak are ignored when computing the centroid. A threshold suppresses the influence of background and noise far away from the spot.
- per_imagebool, optional
If True (default), every image of a stack is centered individually, e.g. to remove beam jitter. If False, the whole stack is shifted by one common shift that centers the centroid of the summed intensity, which preserves the relative positions of the images (e.g. a drifting focus).
- iterationsint, optional
Number of centroid/shift passes. Since the shift is periodic, the first pass may be inexact for spots near the edge or with strong background; further passes refine the result.