Skip to main content

Config-driven calibration-free multi-view DIC workflow.

Project description

PyMultiDIC

PyMultiDIC is a Python-first multi-view digital image correlation workflow. It wraps the full solving process as public Python API calls under pymultidic.<function_name> while keeping native C++ acceleration for the expensive Ncorr-style 2D DIC, CPU-only COLMAP SfM, and 3D reconstruction stages.

The project can be used in two ways:

  • Install the released package with pip install pymultidic and call the API.
  • Build the repository locally, including the native C++ components under native/, then run the same API from source.

The full user manual is available here: docs/pymultidic_usage_en.md.

Example Results

The bundled case/CylinderDIC example was solved through the Python API. A small set of representative result files is stored under docs/results/cylinderdic.

3D morphology cloud map

3D morphology cloud map

Total 3D displacement cloud map

Total displacement cloud map

Displacement component cloud maps

Ux Uy Uz
Ux displacement Uy displacement Uz displacement

Additional copied outputs:

The published example report was regenerated with the embedded native_colmap sparse-source backend and the native_recon3d backend. The current report registers all 12 cameras in one SfM model, starts from 14403 native sparse points, removes 36 spatial sparse-point outliers during product export, and reconstructs 12926 valid 3D displacement points for frame 002.bmp. The SfM mean reprojection error is 0.109651 px.

Install From PyPI

pip install pymultidic

Then call the package from Python:

import pymultidic

config = pymultidic.load_config("configs/MDIC.yaml")
report = pymultidic.run_pipeline(
    config,
    steps=["validate", "sfm", "scale", "mask", "dic2d", "recon3d", "visualize3d"],
)

You can also call the API without a YAML file. In direct-input mode, case_root is required and the remaining paths and numerical parameters use PyMultiDIC defaults unless overridden:

import pymultidic

report = pymultidic.run_pipeline(
    case_root="case/CylinderDIC",
    project_name="CylinderDIC",
    steps=["validate", "sfm", "scale", "mask", "dic2d", "recon3d", "visualize3d"],
    subset_radius=25,
    subset_spacing=6,
    min_corrcoef=0.6,
)

If an MDICConfig object is supplied, it is used as the base configuration. Explicit keyword arguments still override matching fields for that call:

config = pymultidic.load_config("configs/MDIC.yaml")
pymultidic.run_sfm(config, colmap_workspace="colmap_native")

Local Native C++ Build

Use this route when developing the repository, changing files under native/, or validating native builds before publishing wheels. The only supported local source build path is the top-level native/CMakeLists.txt entry point:

  • native_ncorr / libnative_ncorr.a
  • ncorr_cli
  • native_recon3d pybind11 extension
  • native_colmap pybind11 extension

WSL / Linux example:

sudo apt-get update
sudo apt-get install -y \
  build-essential cmake ninja-build python3-dev python3-pip \
  libboost-all-dev libeigen3-dev libceres-dev libflann-dev \
  libopenimageio-dev openimageio-tools libopencv-dev \
  libsqlite3-dev libgflags-dev libgoogle-glog-dev \
  libmetis-dev libsuitesparse-dev libglew-dev qtbase5-dev
python3 -m pip install -U pybind11 scikit-build-core

cmake -S native -B build/wsl-native -G Ninja \
  -DPYBIND11_FINDPYTHON=ON \
  -DPython_EXECUTABLE=/usr/bin/python3 \
  -Dpybind11_DIR=$(python3 -m pybind11 --cmakedir)
cmake --build build/wsl-native

Expected WSL/Linux outputs:

build/wsl-native/ncorr/libnative_ncorr.a
build/wsl-native/ncorr/ncorr_cli
build/wsl-native/recon3d/native_recon3d*.so
build/wsl-native/colmap/native_colmap*.so

Windows example from a Developer PowerShell with CMake and Ninja available:

python -m pip install -U pybind11 scikit-build-core cmake ninja
cmake -S native -B build/windows-native -G Ninja -DPYBIND11_FINDPYTHON=ON
cmake --build build/windows-native

The locally validated Windows build for the embedded COLMAP source port uses a dedicated build/native-colmap-port tree. From this repository root:

cmd /c ""C:\01project\ncorr\.tools\vsbt\VC\Auxiliary\Build\vcvars64.bat" >nul && python -m cmake -S native -B build\native-colmap-port -G Ninja -DCMAKE_MAKE_PROGRAM=C:\Users\LBD\AppData\Roaming\Python\Python313\Scripts\ninja.exe -DCMAKE_BUILD_TYPE=Release -DPYBIND11_FINDPYTHON=OFF -Dpybind11_DIR=C:\Users\LBD\AppData\Roaming\Python\Python313\site-packages\pybind11\share\cmake\pybind11"
cmd /c ""C:\01project\ncorr\.tools\vsbt\VC\Auxiliary\Build\vcvars64.bat" >nul && C:\Users\LBD\AppData\Roaming\Python\Python313\Scripts\ninja.exe -C build\native-colmap-port native_colmap -j 2"

Expected Windows outputs include:

build/windows-native/ncorr/ncorr_cli.exe
build/windows-native/recon3d/native_recon3d*.pyd
build/windows-native/colmap/native_colmap*.pyd
build/native-colmap-port/colmap/native_colmap*.pyd

After the native build, run the full example from the repository root:

python run.py --config configs/MDIC.yaml

run.py automatically prefers local build extensions, including build/native-colmap-port/colmap, before falling back to installed modules, so stale editable installs do not shadow the current checkout.

SfM always uses the embedded native_colmap extension in native/colmap/src. It runs the trimmed COLMAP CorrespondenceGraph, IncrementalMapper, IncrementalTriangulator, and local/global Ceres bundle adjustment sources. There is no runtime backend selection or executable fallback. The native mapper tries multiple initial-image pairs, scores complete models by registration count, per-camera observation counts, camera-center outliers, reprojection error, and 2D coverage, then exports only the selected model. Exported sparse points are additionally filtered by 3D spatial distribution before observations and figures are written. Model summaries, candidate diagnostics, sparse outlier filter statistics, and native backend capabilities are included in sfm_report.json and pipeline_report.json.

The maintained boundary is the narrow native_colmap API plus COLMAP text and Multi-DIC product files. Unused source trees are not shipped.

Public API

Core API functions:

  • pymultidic.load_config(config_path, workspace_root=None)
  • pymultidic.build_config(config=None, *, case_root=None, ...)
  • pymultidic.validate_project(config=None, **kwargs)
  • pymultidic.run_validate(config=None, **kwargs)
  • pymultidic.run_sfm(config=None, **kwargs)
  • pymultidic.run_scale(config=None, **kwargs)
  • pymultidic.run_mask(config=None, **kwargs)
  • pymultidic.run_dic2d(config=None, **kwargs)
  • pymultidic.run_recon3d(config=None, **kwargs)
  • pymultidic.run_visualize3d(config=None, **kwargs)
  • pymultidic.run_step(config_or_step=None, step=None, **kwargs)
  • pymultidic.run_pipeline(config=None, steps=None, stop_on_error=True, **kwargs)

See docs/pymultidic_usage_en.md for the full function-by-function parameter reference, return values, and examples.

Workflow

flowchart TD
    A["Case folder<br/>camera images and calibration images"] --> B["validate<br/>check inputs and output folders"]
    B --> C["sfm<br/>camera geometry, sparse points, observations"]
    C --> D["scale<br/>checkerboard world-scale correction"]
    C --> E["mask<br/>ROI masks from user masks or automatic logic"]
    D --> F["dic2d<br/>native ncorr per-camera 2D DIC"]
    E --> F
    F --> G["recon3d<br/>triangulated 3D displacement and pair surfaces"]
    G --> H["visualize3d<br/>morphology and displacement cloud maps"]
    H --> I["reports, npz, ply, png results"]

Manual step-by-step control:

import pymultidic

config = pymultidic.build_config(
    case_root="case/CylinderDIC",
    project_name="CylinderDIC",
    subset_radius=25,
    subset_spacing=6,
    min_corrcoef=0.6,
)

for step in ["validate", "sfm", "scale", "mask", "dic2d", "recon3d", "visualize3d"]:
    report = pymultidic.run_step(config, step)
    if not report.get("ok"):
        raise RuntimeError(f"{step} failed: {report}")

Output Layout

By default, results are written under <case_root>/<output_root>. For the bundled example this is case/CylinderDIC/results.

Common output folders:

  • logs/: JSON reports for each step and the full pipeline.
  • sfm/colmap/: camera models, sparse points, observations, and COLMAP files.
  • scale/: checkerboard scale correction outputs.
  • masks/: ROI masks, overlays, and debug images.
  • dic2d/: per-camera/per-frame DIC2D .npz outputs.
  • recon3d/: global 3D reconstruction .npz and .ply files.
  • recon3d/pairs/<frame>/: MultiDIC-style pair surface meshes.
  • recon3d/post/<frame>/: pair-surface post-processing results.
  • figures/: 3D visualization outputs.
  • figures/surface_clouds/: morphology, total displacement, and Ux/Uy/Uz cloud maps.

Programmatic access to visualization outputs:

vis_report = pymultidic.run_visualize3d(config)
outputs = vis_report["outputs"]

print(outputs["surface_cloud_morphology"])
print(outputs["surface_cloud_displacement_total"])
print(outputs["surface_cloud_displacement_ux"])
print(outputs["surface_cloud_displacement_uy"])
print(outputs["surface_cloud_displacement_uz"])

Reference Source

reference_code_lib/ is kept as local reference source code. The formal PyMultiDIC implementation lives in the repository root, the pymultidic/ package, the multidic/ implementation modules, and the native C++ projects under native/.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymultidic-0.1.8.tar.gz (8.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pymultidic-0.1.8-cp312-cp312-win_amd64.whl (9.2 MB view details)

Uploaded CPython 3.12Windows x86-64

File details

Details for the file pymultidic-0.1.8.tar.gz.

File metadata

  • Download URL: pymultidic-0.1.8.tar.gz
  • Upload date:
  • Size: 8.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pymultidic-0.1.8.tar.gz
Algorithm Hash digest
SHA256 90394bed2d5147931224f081596c9470969892a264fd34f42584c46d4d807096
MD5 b6c851ab7c3e32ac701ed04c543f359d
BLAKE2b-256 5ba5caca43b72c5dc59e5be63afdb0cbb89b299e85cbeb80420d9cb4ad9836bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymultidic-0.1.8.tar.gz:

Publisher: wheels.yml on lbd-hfut/Multi-DIC

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pymultidic-0.1.8-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: pymultidic-0.1.8-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 9.2 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pymultidic-0.1.8-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 05a9e445e68741ec5b69516f4d93fbcbbe80ec71a6e6ff25cac01ee2643a1595
MD5 205b70c247c3a339ae966570c1bb9650
BLAKE2b-256 b9348b9066501a11885753ad6bf402e4f83787394415c4af21806329e8b64a22

See more details on using hashes here.

Provenance

The following attestation bundles were made for pymultidic-0.1.8-cp312-cp312-win_amd64.whl:

Publisher: wheels.yml on lbd-hfut/Multi-DIC

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page