3.1.1. fringes package
3.1.1.1. Submodules
3.1.1.2. fringes.filter module
- fringes.filter.curvature(s: ndarray, calibrated: bool = False, normalize: bool = True) ndarray[source]
Mean curvature map.
Computed by differentiating a slope map.
- Parameters:
s (np.ndarray) – Slope map. It is reshaped to video-shape (frames T, height Y, width X, color channels C) before processing.
calibrated (bool, optional) – Flag indicating whether the input data s originates from a calibrated measurement. Default is False. If this is False, the median value of the computed curvature map is added as an offset, so the median value of the final curvature map becomes zero.
normalize (bool) – Flag indicating whether to use the acrtangent function to non-linearly map the codomain from [-inf, inf] to [-1, 1]. Default is True.
- Returns:
c – Curvature map.
- Return type:
np.ndarray
- fringes.filter.direct(b: ndarray)[source]
Direct illumination component.
- Parameters:
b (np.ndarray) – Modulation
- Returns:
d – Direct illumination component.
- Return type:
np.ndarray
References
- fringes.filter.exposure(a: ndarray, I_rec: ndarray, lessbits: bool = True)[source]
Exposure.
- Parameters:
a (np.ndarray) – Brightness.
I_rec (np.ndarray) – Fringe pattern sequence.
lessbits (bool, optional) – The camera recorded I_rec may contain fewer bits of information than its data type can hold, e.g. 12 bits for dtype uint16. If this flag is activated, it looks for the maximal value in I and sets Imax to the same or next power of two which is divisible by two. Example: If I.max() is 3500, Imax is set to 4095 (the maximal value a 12bit camera can deliver).
- Returns:
E – Exposure.
- Return type:
np.ndarray
3.1.1.3. fringes.fringes module
This module contains the handy `Fringes`class.
It handles all the required parameters for configuring fringe pattern sequences and provides methods for creating and analyzing them.
- class fringes.fringes.Fringes(*args, Y: int = 1200, X: int = 1920, H: int = 1, M: float = 1.0, D: int = 2, K: int = 3, T: int = 24, N: tuple | list | ndarray = array([[4, 4, 4], [4, 4, 4]]), l: tuple | list | ndarray = array([[147.69230769, 274.28571429, 21.57303371], [147.69230769, 274.28571429, 21.57303371]]), v: tuple | list | ndarray = array([[13., 7., 89.], [13., 7., 89.]]), f: tuple | list | ndarray = array([[1., 1., 1.], [1., 1., 1.]]), h: tuple | list | ndarray = array([[255, 255, 255]]), p0: float = 3.141592653589793, gamma: float = 1.0, A: float = 127.5, B: float = 127.5, E: float = 0.5, V: float = 1.0, alpha: float = 1.0, dtype: str | dtype = 'uint8', grid: str = 'image', axis: int = 0, SDM: bool = False, WDM: bool = False, FDM: bool = False, static: bool = False, lmin: float = 8.0, indexing: str = 'xy', reverse: bool = False, ui: float = 0.28867513459481287, PSF: float = 0.0, mode: str = 'fast')[source]
Bases:
objectEasy-to-use class to configure, encode and decode customized fringe patterns using phase shifting algorithms.
- Parameters:
*args (tuple) – Non-keyword arguments are explicitly discarded. Only keyword arguments are considered.
A (<class 'float'>, default = 127.5) – Bias.
B (<class 'float'>, default = 127.5) – Amplitude.
D (<class 'int'>, default = 2) – Number of directions.
E (<class 'float'>, default = 0.5) – Relative exposure, i.e. relative mean intensity ∈ [0, 1].
FDM (<class 'bool'>, default = False) – Frequency division multiplexing.
H (<class 'int'>, default = 1) – Number of hues.
K (<class 'int'>, default = 3) – Number of sets (number of fringe patterns with different spatial frequencies).
M (<class 'float'>, default = 1.0) – Number of averaged intensity samples.
N (array_like, default = [[4 4 4]) –
- [4 4 4]]
Number of phase shifts.
PSF (<class 'float'>, default = 0.0) – Standard deviation of Point Spread Function for defocus.
SDM (<class 'bool'>, default = False) – Spatial division multiplexing.
T (<class 'int'>, default = 24) – Number of frames.
V (<class 'float'>, default = 1.0) – Fringe visibility (fringe contrast) ∈ [0, 1].
WDM (<class 'bool'>, default = False) – Wavelength division multiplexing.
X (<class 'int'>, default = 1920) – Width of fringe patterns.
Y (<class 'int'>, default = 1200) – Height of fringe patterns.
alpha (<class 'float'>, default = 1.0) – Factor for extending the coding range L.
axis (<class 'int'>, default = 0) – Axis along which to shift if number of directions equals one.
dtype (str | numpy.dtype, default = uint8) – Data type.
f (tuple | list | numpy.ndarray, default = [[1. 1. 1.]) –
- [1. 1. 1.]]
Temporal frequency (number of periods to shift over).
gamma (<class 'float'>, default = 1.0) – Gamma correction factor used to compensate nonlinearities of the display response curve.
grid (<class 'str'>, default = image) – Coordinate system of the fringe patterns.
h (array_like, default = [[255 255 255]]) – Hues i.e. colors of fringe patterns.
indexing (<class 'str'>, default = xy) – Indexing convention.
l (array_like, default = [[147.69230769 274.28571429 21.57303371]) –
- [147.69230769 274.28571429 21.57303371]]
Wavelengths of fringe periods.
lmin (<class 'float'>, default = 8.0) – Minimum resolvable wavelength.
mode (<class 'str'>, default = fast) – Mode for decoding.
p0 (<class 'float'>, default = 3.141592653589793) – Phase offset within interval (-2pi, +2pi).
reverse (<class 'bool'>, default = False) – Flag for shifting fringes in reverse direction.
static (<class 'bool'>, default = False) – Flag for creating static fringes (so they remain congruent when shifted).
ui (<class 'float'>, default = 0.28867513459481287) – Intensity noise.
v (array_like, default = [[13. 7. 89.]) –
- [13. 7. 89.]]
Spatial frequencies (number of periods/fringes across maximum coding length ‘L’).
- property A: float
Bias.
- property B: float
Amplitude.
- property C: int
Number of color channels.
- property D: int
Number of directions.
- property DR: ndarray
Dynamic range of the phase shift coding.
It is a measure of how many points can be distinguished within the unambiguous measurement range [0, UMR).
- property DRdB: ndarray
Dynamic range. [DRdB] = dB.
- property E: float
Relative exposure, i.e. relative mean intensity ∈ [0, 1].
- property FDM: bool
Frequency division multiplexing.
The directions ‘D’ and the sets K are multiplexed, resulting in a crossed fringe pattern if ‘D’ ≡ 2. It can only be activated if ‘D’ ∨ ‘K’ > 1 i.e. ‘D’ * ‘K’ > 1. The amplitude ‘b’ is reduced by the factor ‘D’ * ‘K’. Usually ‘f’ equals 1 and is essentially only changed if frequency division multiplexing (‘FDM’) is activated: Each set per direction receives an individual temporal frequency ‘f’, which is used in temporal demodulation to distinguish the individual sets. A minimal number of shifts Nmin ≥ ⌈ 2 * fmax + 1 ⌉ is required to satisfy the sampling theorem and N is updated automatically if necessary. If one wants a static pattern, i.e. one that remains congruent when shifted, set ‘static’ to True.
- property H: int
Number of hues.
- property Imax: int
Maximum gray value.
- property K: int
Number of sets (number of fringe patterns with different spatial frequencies).
- property L: float
Coding range. [L] = px.
- property M: ndarray
Number of averaged intensity samples.
- property MM_: ndarray
Coefficients for Chinese remainder theorem.
- property N: ndarray
Number of phase shifts.
- property PSF: float
Standard deviation of Point Spread Function for defocus. [PSF] = px.
- property R: ndarray
Lengths of fringe patterns for each direction. [R] = px.
- property SDM: bool
Spatial division multiplexing.
The directions ‘D’ are multiplexed, resulting in a crossed fringe pattern. The amplitude ‘B’ is halved. It can only be activated if we have two directions, i.e. ‘D’ ≡ 2. The number of frames ‘T’ is reduced by the factor 2.
- property SNR: ndarray
Signal-to-noise ratio of the phase shift coding.
It is a measure of how many points can be distinguished within the screen length [0, R).
- property SNRdB: ndarray
Signal-to-noise ratio. [SNRdB] = dB.
- property T: int
Number of frames.
- property UMR: ndarray
Unambiguous measurement range. [UMR] = px
The coding is only unique within the interval [0, UMR); after that it repeats itself.
The UMR is derived from ‘l’ and ‘v’:
If ‘l’ ∈ ℕ, UMR = lcm(‘l’), with lcm() being the least common multiple.
Else, if ‘v’ ∈ ℕ, UMR = ‘L’ / gcd(‘v’), with gcd() being the greatest common divisor.
Else, if ‘l’ ∨ ‘v’ ∈ ℚ, lcm() resp. gcd() are extended to rational numbers.
Else, if ‘l’ ∧ ‘v’ ∈ ℝ ∖ ℚ, UMR = prod(‘l’), with prod() being the product operator.
- property V: float
Fringe visibility (fringe contrast) ∈ [0, 1].
- property WDM: bool
Wavelength division multiplexing.
The shifts are multiplexed into the color channel, resulting in an RGB fringe pattern. It can only be activated if all shifts equal 3, i.e. ‘N’ ≡ 3. The number of frames ‘T’ is reduced by the factor 3.
- property X: int
Width of fringe patterns. [X] = px.
- property Y: int
Height of fringe patterns. [Y] = px.
- property alpha: float
Factor for extending the coding range L.
- property axis: int
Axis along which to shift if number of directions equals one.
Either 0 or 1.
- coordinates() ndarray[source]
Generate the coordinate matrices of the coordinate system defined in grid.
- Returns:
x – Coordinate matrices.
- Return type:
np.ndarray
- decode(I: ndarray, Vmin: float = 0, verbose: bool | str = False, check_overexposure: bool = False, deinterlace: bool = False, despike: bool = False, denoise: bool = False) namedtuple[source]
Decode fringe patterns.
- Parameters:
I (np.ndarray | list) –
Fringe pattern sequence. It is reshaped to video-shape (frames T, height Y, width X, color channels C) before processing.
Note
It must have been encoded with the same parameters set to the Fringes instance as the encoded one.
Vmin (float) – Minimum visibility for measurement to be valid (can accelerate decoding).
verbose (bool or str, optional) – If this or the argument verbose of the Fringes instance is set to True, intermediate and verbose results are returned as well.
check_overexposure (bool, optional) – If this flag is set to True, ‘I’ is checked for overexposure and if so a warning is logged.
deinterlace (bool, optional) – If this flag is set to True, deinterlacing is activated.
despike (bool, optional) – If this flag is set to True, single pixel outliers in the unwrapped phase map are replaced by their local neighborhood using a median filter.
denoise (bool, optional) – If this flag is set to True, the unwrapped phase map is smoothened by a bilateral filter which is edge-preserving.
- Returns:
brightness (np.ndarray) – Local background signal.
modulation (np.ndarray) – Local amplitude of the cosine signal.
registration (np.ndarray) – Decoded coordinates.
Note
The registration is a mapping in the same pixel grid as the camera sensor and contains the information where each camera pixel, i.e. each camera sightray, was looking at during the fringe pattern recording.
phase (np.ndarray, optional) – Local phase.
orders (np.ndarray, optional) – Fringe orders.
residuals (np.ndarray, optional) – Residuals from the optimization-based unwrapping process.
uncertainty (np.ndarray, optional) – uncertainty of positional decoding in pixel units
- Raises:
ValueError – If the number of frames of I and the attribute T of the Fringes instance don’t match.
ValueError – If ‘WDM’ is active but ‘I’ does not have 3 color channels.
Examples
>>> from fringes import Fringes >>> f = Fringes() >>> I = f.encode()
>>> a, b, x = f.decode(I)
Also return interediate and verbose results:
>>> a, b, x, p, k, r, u = f.decode(I, verbose=True)
- property dtype: dtype
Data type.
The following values can be set:
‘uint8’
‘uint16’
‘float32’
‘float64’
- encode(frames: int | tuple | list | ndarray | None = None) ndarray[source]
Encode fringe patterns.
- Parameters:
frames (array_like, optional) – Indices of the frames to be encoded. The default, frames=None, will encode all frames at once. If frames is negative, it counts from the last to the first frame. If frames contains numbers whose magnitude is larger than the total number of frames (as specified by the attribute T of the Fringes instance), it is wrapped around. If frames is a tuple of ints, only the frames specified in the tuple are encoded. If indices occur more than once, only the first occurence is encoded.
- Returns:
I – Fringe pattern sequence.
- Return type:
np.ndarray
Notes
To receive the frames iteratively (i.e. in a lazy manner), simply iterate over the Fringes instance. Alternatively, to receive arbitrary frames, index the Fringes instance directly, either with an integer, a tuple or a slice.
Examples
>>> from fringes import Fringes >>> f = Fringes()
Encode the complete fringe pattern sequence.
>>> I = f.encode()
Encode the first frame of the fringe pattern sequence.
>>> I = f.encode(frames=0) >>> I = f[0] >>> I = next(iter(f))
Encode the last frame of the fringe pattern sequence.
>>> I = f.encode(frames=-1) >>> I = f[-1]
Encode the first two frames of the fringe pattern sequence.
>>> I = f.encode(frames=(0, 1)) >>> I = f[0, 1] >>> I = f[:2]
Create a generator to receive the frames iteratively, i.e. in a lazy manner.
>>> I = (frame for frame in f)
- property eta: float
Coding efficiency.
- property f: ndarray
Temporal frequency (number of periods to shift over).
- property gamma: float
Gamma correction factor used to compensate nonlinearities of the display response curve.
- property grid: str
Coordinate system of the fringe patterns.
The following values can be set:
‘image’: The top left corner pixel of the grid is the origin and positive directions are right- resp. downwards.
‘Cartesian’: The center of grid is the origin and positive directions are right- resp. upwards.
‘polar’: The center of grid is the origin and positive directions are clockwise resp. outwards.
‘log-polar’: The center of grid is the origin and positive directions are clockwise resp. outwards.
- property h: ndarray
Hues i.e. colors of fringe patterns.
Possible values are any sequence of RGB color triples within the interval [0, 255]. However, black (0, 0, 0) is not allowed.
The hue values can also be set by assigning any combination of the following characters as a string:
‘r’: red
‘g’: green
‘b’: blue
‘c’: cyan
‘m’: magenta
‘y’: yellow
‘w’: white
Before decoding, repeating hues will be fused by averaging.
- property indexing: str
Indexing convention.
Cartesian indexing xy (the default) will index the row first, while matrix indexing ij will index the colum first.
- property l: ndarray
Wavelengths of fringe periods. [l] = px.
When L changes, v is kept constant and only l is changed.
- property lmin: float
Minimum resolvable wavelength. [lmin] = px.
- load(fname: str | None = None) None[source]
Load parameters from a config file to the Fringes instance.
Warning
The parameters are only loaded if the config file provides the section fringes.
- Parameters:
fname (str, optional) – File name of the file to load. Supported file formats are: *.json, *.yaml, *.toml. If fname is not provided, the file .fringes.yaml within the user home directory is loaded.
Examples
>>> import os >>> fname = os.path.join(os.path.expanduser("~"), ".fringes.yaml")
>>> from fringes import Fringes >>> f = Fringes() >>> f.N += 1 >>> f.save(fname)
>>> f2 = Fringes() >>> f2.load(fname)
>>> f2 == f True
- property mode: str
Mode for decoding.
The following values can be set:
‘fast’
‘precise’
- mtf(v: int | float | tuple[int | float] | list[int | float] | ndarray | None = None) ndarray[source]
Modulation Transfer Function,
normalized to values within [0, 1].
- Parameters:
v (array_like) – Spatial frequencies at which to determine the normalized modulation.
- Returns:
b – Relative modulation, at spatial frequencies ‘v’. ‘b’ is in the same shape as ‘v’.
- Return type:
np.ndarray
- Raises:
ValueError – If ‘v’ contains negative numbers.
Notes
If the private attribute _mtf of the Fringes instance is not None, the MTF is interpolated from previous measurements.
Else, if the attribute PSF of the Fringes instance is larger than zero, the MTF is computed from the optical transfer function of the optical system, i.e. as the magnitude of the Fourier-transformed ‘Point Spread Function’ (PSF).
Else, it returns ones.
- optimize(T: int | None = None, umax: float | None = None) None[source]
Optimize the parameters of the Fringes instance.
- Parameters:
T (int, optional) – Number of frames. If T is not provided, the number of frames from the Fringes instance is used. Then, the Fringes instance’s number of shifts N is distributed optimally over the directions and sets.
umax (float, optional) – Maximum allowable uncertainty. Must be greater than zero. Standard deviation of maximum uncertainty for measurement to be valid. [umax] = px.
Notes
todo: update
If umax is specified, the parameters are determined that allow a maximal uncertainty of umax with a minimum number of frames.
Else, the parameters of the Fringes instance are optimized to yield the minimal uncertainty using the given number of frames T.
- property p0: float
Phase offset within interval (-2pi, +2pi).
It can be used to e.g. let the fringe patterns start (at the origin) with a gray value of zero.
- property reverse: bool
Flag for shifting fringes in reverse direction.
- save(fname: str | None = None) None[source]
Save the parameters of the Fringes instance to a config file.
Within the file, the parameters are written to the section fringes.
- Parameters:
fname (str, optional) – File name of the file to save. Supported file formats are: *.json, *.yaml, *.toml. If fname is not provided, the parameters are saved to the file .fringes.yaml within the user home directory.
Examples
>>> import os >>> fname = os.path.join(os.path.expanduser("~"), ".fringes.yaml")
>>> from fringes import Fringes >>> f = Fringes()
>>> f.save(fname)
- set_mtf(b: ndarray)[source]
Set the modulation transfer function (MTF).
- Parameters:
b (np.ndarray) – Measured modulation.
- Raises:
ValueError – If ‘b’ contains negative values.
Notes
The normalized modulation transfer function is a cubic spline interpolator. It is set to the private attribute ‘_mtf’ and used when the method ‘mtf()’ is called.
- property shape: tuple[int, int, int, int]
Shape of fringe pattern sequence in video shape (frames, height, with, color channels).
- property static: bool
Flag for creating static fringes (so they remain congruent when shifted).
- property t: ndarray
Greatest common divisor of moduli.
- property u: ndarray
Measurement uncertainty. [u] = px.
It is based on the phase noise model and propagated through the unwrapping process and the phase fusion.
- property ui: float
Intensity noise.
- property upi: float
Phase uncertainties. [upi] = rad
- property uwr: str
Phase unwrapping method.
- property uxi: ndarray
Positional uncertainties.
- property v: ndarray
Spatial frequencies (number of periods/fringes across maximum coding length ‘L’).
- values = {'dtype': ('uint8', 'uint16', 'float32', 'float64'), 'grid': 'image', 'indexing': ('xy', 'ij'), 'mode': ('fast', 'precise')}
- property vmax: float
Maximum resolvable spatial frequency.
- property vopt: float
Optimal spatial frequency for minimal decoding uncertainty.
- property x: ndarray
Coordinate matrices of the coordinate system defined in grid.
- property x0: ndarray
Coordinate offset.
3.1.1.4. fringes.grid module
3.1.1.5. fringes.util module
- fringes.util.bilateral(I: ndarray, k: int = 7) ndarray[source]
Bilateral filter.
Edge-preserving, denoising filter.
- Parameters:
I (np.ndarray) – Input data. It is reshaped to video-shape (frames ‘T’, height ‘Y’, width ‘X’, color channels ‘C’) before processing.
k (int, optional) – Size of the filter kernel. Default is 7.
- Returns:
out – Filtered data.
- Return type:
np.ndarray
- fringes.util.circular_distance(a: float | ndarray, b: float | ndarray, c: float) ndarray[source]
Circular distance.
- Parameters:
a (float or np.ndarray) – Start points.
b (float or np.ndarray) – End points.
c (float) – Circumference (distance) after which wrapping occurs.
- Returns:
d – Circular distance from a to b.
- Return type:
float or np.ndarray
Notes
For more details, see https://ieeexplore.ieee.org/document/9771407.
- fringes.util.gamma_auto_correct(I: ndarray) ndarray[source]
Automatically estimate and apply the gamma correction factor to linearize the display/camera response curve.
- Parameters:
I (np.ndarray) – Recorded data.
- Returns:
I_lin – Linearized data.
- Return type:
np.ndarray
- fringes.util.simulate(I: ndarray, PSF: float = 0, system_gain: float = 0.038, dark_current: float = 95.78947368421053, dark_noise: float = 13.7, seed: int = 268664434431581513926327163960690138719) ndarray[source]
Simulate the recording, i.e. the transmission channel.
This includes the modulation transfer function (computed from the imaging system’s point spread function) and intensity noise added by the camera.
- Parameters:
I (np.ndarray) – Fringe pattern sequence.
PSF (float, optional) – Standard deviation of the Point Spread Function, in pixel units. The default is 0.
system_gain (float, optional) – System gain of the digital camera. The default is 0.038.
dark_current (float, optional) – Dark current of the digital camera, in unit electrons. The default is ~100.
dark_noise (float, optional) – Dark noise of the digital camera, in units electrons. The default is 13.7.
seed (int, optional) – A seed to initialize the Random Number Generator. It makes the random numbers predictable. See Seeding and Entropy for more information about seeding.
- Returns:
I – Simulated fringe pattern sequence.
- Return type:
np.ndarray
- fringes.util.vshape(data: ndarray, channels: list | tuple = (1, 3, 4)) ndarray[source]
Standardizes the input data shape.
Transforms video data into the standardized shape (T, Y, X, C), where T is number of frames, Y is height, X is width, and C is number of color channels.
Inspired from scikit-video.
- Parameters:
data (ndarray) – Input data of arbitrary shape.
channels (list | tuple) – Allowed number of color channels.
- Returns:
videodata – Standardized version of data, in shape (T, Y, X, C), where T is number of frames, Y is height, X is width, and C is number of color channels.
- Return type:
ndarray
Notes
Ensures that the array becomes 4-dimensional and that the length of the last dimension is in ‘channels’). To do this, leading dimensions may be flattened.
Examples
>>> from fringes import vshape
>>> data = np.ones(100) >>> videodata = vshape(data) >>> videodata.shape (100, 1, 1, 1)
>>> data = np.ones((1200, 1920)) >>> videodata = vshape(data) >>> videodata.shape (1, 1200, 1920, 1)
>>> data = np.ones((1200, 1920, 3)) >>> videodata = vshape(data) >>> videodata.shape (1, 1200, 1920, 3)
>>> data = np.ones((100, 1200, 1920)) >>> videodata = vshape(data) >>> videodata.shape (100, 1200, 1920, 1)
>>> data = np.ones((100, 1200, 1920, 3)) >>> videodata = vshape(data) >>> videodata.shape (100, 1200, 1920, 3)
>>> data = np.ones((2, 3, 4, 1200, 1920)) >>> videodata = vshape(data) >>> videodata.shape (24, 1200, 1920, 1)
3.1.1.6. Module contents
Phase shifting algorithms for encoding and decoding sinusoidal fringe patterns.