Current version: 0.1.1
Documentation: https://moirestrain.readthedocs.io/en/latest/
NumPy-first tools for phase-shifted sampling moire analysis of periodic
grating images. moirestrain targets full-field micro-displacement and
micro-strain measurement from reference/deformed grid images.
moirestrain estimates phase fields from periodic grating images and converts
reference/deformed phase differences into displacement and small-strain fields.
The current high-level workflow focuses on two-dimensional square-marker grid
targets, such as regularly spaced black squares on a white background.
- Generate phase-shifted sampling moire images from a single grating image.
- Estimate wrapped phase and convert reference/deformed phase differences into displacement.
- Analyze square-grid targets in both x/y directions.
- Compute
u,v,exx,eyy, andgamma_xyfields. - Detect partial grating ROIs inside larger images using grating-energy maps.
- Rectify oblique planar grid targets from four corner points.
- Separate square-grid images into x-periodic and y-periodic components.
- Export
.npzarrays, valid ROI masks, and PNG summaries for reproducible workflows.
The numerical core is NumPy-based. Runtime dependencies also include
imageio and matplotlib for CLI image I/O and PNG reporting. scikit-image
is used only by optional examples and development tests.
For N equally phase-shifted moire images,
moirestrain estimates the wrapped phase from the first Fourier component:
The displacement component along the analyzed grating direction is then calculated from the deformed/reference phase difference:
Here p is grating_pitch; when it is given in pixels, the displacement is
returned in pixels.
This example detects a square-grid patch inside a larger image, shows the grating-energy ROI detection, and compares measured strain against the known synthetic truth.
The synthetic example starts from an ideal square-marker grid, samples it with
sub-pixel averaging, and creates a deformed image by evaluating the same
grid at coordinates shifted by known displacement fields u(x, y) and
v(x, y). The ground-truth strain fields are calculated directly from those
displacement gradients:
Install the released package from PyPI with pip:
pip install moirestrainOr add it to a Poetry project:
poetry add moirestrainFor local development:
poetry installRun tests:
poetry run pytestBuild distributions:
poetry buildfrom moirestrain import analyze_grid, recommended_strain_smoothing_window
period = 16
strain_window = recommended_strain_smoothing_window(period, cycles=3)
result = analyze_grid(
reference_image,
deformed_image,
period=period,
strain_smooth_window=strain_window,
)
u = result.x.displacement
v = result.y.displacement
exx = result.strain.exx
eyy = result.strain.eyy
gamma_xy = result.strain.gamma_xyFor one-direction grating analysis:
from moirestrain import phase_shifted_sampling_moire
result = phase_shifted_sampling_moire(
reference_image,
deformed_image,
period=8,
axis="x",
grating_pitch=8.0,
)
u = result.displacementAnalyze a manually cropped square-grid ROI:
moirestrain analyze-grid ref.png def.png \
--period 16 \
--roi y0,x0,y1,x1 \
--out result.npz \
--figure result.pngDetect the dominant grating ROI automatically:
moirestrain analyze-grid ref.png def.png \
--period 16 \
--auto-roi \
--out result.npz \
--figure result.pngCreate a four-corner calibration, rectify an image pair, then analyze:
moirestrain make-calibration \
--image-points x0,y0,x1,y1,x2,y2,x3,y3 \
--output-shape 240,320 \
--period 16 \
--out calibration.json
moirestrain rectify-pair ref.png def.png \
--calibration calibration.json \
--reference-out rectified_ref.npy \
--deformed-out rectified_def.npy \
--metadata-out rectification_metadata.json
moirestrain analyze-grid ref.png def.png \
--period 16 \
--calibration calibration.json \
--out result.npz \
--figure result.pngIf physical dimensions are known, pass --world-points and --unit to
make-calibration. The analysis output then includes u_physical,
v_physical, pixel_spacing, and physical-coordinate strain fields.
Use --no-figure for batch jobs that only need .npz arrays.
Generate synthetic data, run benchmarks, and build figures:
PYTHONPATH=src python examples/benchmark_microstrain.py
PYTHONPATH=src python examples/benchmark_sweep.py
PYTHONPATH=src python examples/partial_grid_detection_analysis.py
PYTHONPATH=src python examples/skimage_natural_grating_strain.pyRunnable learning-oriented workflows are under tutorials/:
PYTHONPATH=src python tutorials/01_square_grid_analysis.py
PYTHONPATH=src python tutorials/02_partial_grid_detection.py
PYTHONPATH=src python tutorials/03_four_corner_rectification.pyOther examples:
PYTHONPATH=src python examples/generate_experiment.py
PYTHONPATH=src python examples/microstrain_square_grid.py
PYTHONPATH=src python examples/strain_distribution.py
PYTHONPATH=src python examples/perspective_rectification.pyBuild documentation assets and Sphinx HTML:
PYTHONPATH=src python scripts/build_docs_assets.py
poetry run sphinx-build -b html docs docs/_build/html- Use a camera-space grid pitch around
12-16 pxor larger when possible. - Square-marker targets contain strong harmonics; strain estimation needs smoothing before differentiation.
- Evaluate and display only a valid inner ROI near image boundaries.
- For tilted planar targets, rectify from four corner points before analysis.
- For real images, check illumination, blur, noise, grid pitch calibration, and registration between reference/deformed frames.
MIT License. See LICENSE.
