Theory notes
Sampling moire phase
The sampling moire method generates multiple phase-shifted moire images from a single grating image by thinning the image at different sampling offsets and interpolating each sampled image back to the original grid.
For equally shifted images
the wrapped phase can be estimated from the first Fourier component:
In moirestrain, phase_shifted_stack generates the phase-shifted moire
image stack and wrapped_phase applies this phase-shifting formula. The
high-level entry point phase_shifted_sampling_moire runs the complete
single-direction workflow.
Square-marker grid targets
For a square-marker grid target, the captured image is treated as a grayscale
image after camera pixel averaging. separate_grid_components first applies
directional smoothing: smoothing along y isolates the x-periodic component,
and smoothing along x isolates the y-periodic component. analyze_grid then
applies the phase-shifted sampling moire workflow to each component and
computes the small-strain field.
Displacement from phase difference
The displacement component aligned with the analyzed grating direction is calculated from the phase difference between deformed and reference images:
Here p is the grating pitch in the displacement unit of interest. If the
pitch is expressed in pixels, the displacement is returned in pixels.
Strain field direction
Small strain is obtained from spatial gradients of displacement:
moirestrain.strain_field provides these small-strain components. For noisy
experimental data, use the smooth_window option because differentiating a
noisy displacement field directly amplifies high-frequency noise.
Perspective rectification
For a planar specimen surface, camera tilt can be modeled by a homography:
moirestrain.rectify_image estimates this transform from four image corner
points and resamples the grating ROI into a fronto-parallel image. Phase,
displacement, and strain analysis should then be performed in the rectified
coordinate system. If physical corner coordinates are available,
PerspectiveCalibration.pixel_spacing can be passed to strain_field as
spacing=(dy, dx).