Skip to content

kevin-tofu/moirestrain

Repository files navigation

moirestrain

Python tests Documentation Status PyPI version Python versions License: MIT

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.

What It Can Do

  • 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, and gamma_xy fields.
  • 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 .npz arrays, 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.

Method Formulae

For N equally phase-shifted moire images,

$$ I_k = a + b \cos\left(\phi + \frac{2\pi k}{N}\right), $$

moirestrain estimates the wrapped phase from the first Fourier component:

$$ \phi = \mathrm{atan2}\left( -\sum_{k=0}^{N-1} I_k \sin\frac{2\pi k}{N}, \sum_{k=0}^{N-1} I_k \cos\frac{2\pi k}{N} \right). $$

The displacement component along the analyzed grating direction is then calculated from the deformed/reference phase difference:

$$ u = \frac{\Delta\phi}{2\pi} p, \quad \Delta\phi = \phi_\mathrm{deformed} - \phi_\mathrm{reference}. $$

Here p is grating_pitch; when it is given in pixels, the displacement is returned in pixels.

Results

Partial-Grid Strain Recovery

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.

partial grid measured true strain comparison

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:

$$ e_{xx} = \frac{\partial u}{\partial x}, \quad e_{yy} = \frac{\partial v}{\partial y}, \quad \gamma_{xy} = \frac{\partial u}{\partial y} + \frac{\partial v}{\partial x}. $$

Installation

Install the released package from PyPI with pip:

pip install moirestrain

Or add it to a Poetry project:

poetry add moirestrain

For local development:

poetry install

Run tests:

poetry run pytest

Build distributions:

poetry build

Quick Start

from 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_xy

For 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.displacement

CLI

Analyze 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.png

Detect the dominant grating ROI automatically:

moirestrain analyze-grid ref.png def.png \
  --period 16 \
  --auto-roi \
  --out result.npz \
  --figure result.png

Create 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.png

If 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.

Examples

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.py

Runnable 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.py

Other 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.py

Build documentation assets and Sphinx HTML:

PYTHONPATH=src python scripts/build_docs_assets.py
poetry run sphinx-build -b html docs docs/_build/html

Notes For Experiments

  • Use a camera-space grid pitch around 12-16 px or 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.

Citation

License

MIT License. See LICENSE.

Packages

 
 
 

Contributors