Note
This is pyOpenLPT-refraction (https://github.com/clockj/pyOpenLPT-refraction), a branch of OpenLPT for cameras that look through refractive windows: flat walls, tubes and spheres, with wand calibration through flat walls and tubes (see below). It will be merged into the main OpenLPT repository, https://github.com/JHU-NI-LAB/OpenLPT_GUI, later.
OpenLPT is a powerful, user-friendly open-source software for 3D Lagrangian Particle Tracking (LPT), designed for experimental fluid dynamics and flow visualization. Developed by the Ni Research Lab at Johns Hopkins University (JHU), it provides a comprehensive GUI-based workflow for high-precision particle tracking and reconstruction.
- 3D Particle Tracking: Robust Lagrangian tracking (LPT) and Shake-the-Box (STB) methods.
- Multi-Camera Calibration: Easy-to-use tools for wand and plate calibration (intrinsic & extrinsic parameters).
- New in this branch, calibration through refractive windows: camera models for flat windows (
PINPLATE), tubes (PINCYL) and spherical windows (PINSPH), and wand calibration through flat windows (Pinhole+Refraction) and tubes (Pinhole+Cylinder). The refraction is modelled exactly, so the cameras need not face the window squarely.
- New in this branch, calibration through refractive windows: camera models for flat windows (
- Cross-Platform: Full support for Windows, macOS, and Linux.
- Performance: High-performance C++ core with Python Python bindings for flexibility and speed.
Keywords: Lagrangian Particle Tracking (LPT), Shake-the-Box (STB), 3D Flow Visualization, PIV, Particle Reconstruction, Multi-camera Calibration, Experimental Fluid Dynamics, JHU Ni Research Lab.
Tip
Ensure you have activated your environment before running these commands: conda activate OpenLPT
(On Windows, we recommend using Command Prompt (CMD) as PowerShell may have execution policy restrictions).
# Launch the interactive GUI
openlpt-gui# Run STB tracking directly with a config file
openlpt path/to/config.txt
# Show image preprocessing CLI help
openlpt preprocess --helpimport openlpt as lpt
# Run tracking programmatically
lpt.run('path/to/config.txt')
# Or launch GUI from within a script
lpt.launch_gui()demo.mp4
A camera that looks into water through a tank wall or a tube sees particles displaced, stretched, hidden or even doubled. This branch models the refraction exactly: the projection of a 3-D point returns every pixel at which it appears, or none, and the wand calibration fits the cameras through the window from images of a moving wand. Two real calibrations:
Run 2026-10-08: three high-speed cameras around an acrylic tube full of water (outer diameter 201.6 mm, wall
3.2 mm), camera model PINCYL (Pinhole+Cylinder in the GUI).
- The wand calibration used 7212 frames, with a reprojection RMS of 0.70 px.
- The calibrated cameras rebuild the 10 mm wand to 61 µm RMS (0.61 %), frame by frame over 7175 frames.
- With this calibration OpenLPT tracked a swirling flow through the wall: 411 tracks, 250 frames at 4000 fps.
Run 2026-07-27: four cameras about 1 m from a corner of a water tank, looking through its two perpendicular 12.7 mm
acrylic walls into a 150 × 100 mm channel, camera model PINPLATE (Pinhole+Refraction in the GUI).
- The wand calibration used 10936 frames, with a median reprojection error of 0.22 px.
- The calibrated cameras rebuild the 10 mm wand with a median error of 6.8 µm and an SD of 10.2 µm (0.10 %).
To use it: in the GUI, Calibration → Wand Calibration, with the camera model Pinhole+Refraction (flat
windows) or Pinhole+Cylinder (a tube). The Wand Calibration User Guide
goes through it step by step. The figures are drawn from the two calibrations' saved results by
assets/readme/make_readme_figures.py.
The method: S. Zhong, S. Tan, X. Zhang, Y. Li and R. Ni, "A complete forward projection algorithm through cylindrical and spherical refractive windows", arXiv:2610.17413 (2026).
- User-friendly interface in python
- Lagrangian particle tracking for multiple objects (point-like particles, spherical particles, etc.)
- Support stereomatching with multiple cameras (at least 2)
- Include multiple test cases for users to test and understand the code
- Better structure for adding new functions
We provide automated scripts that set up everything for you (including Conda, environment, and dependencies).
-
Download the code:
git clone https://github.com/JHU-NI-LAB/OpenLPT_GUI.git cd OpenLPT_GUI -
Run the Installer:
-
Windows: Double-click
install_windows.bat(Or run in terminal:install_windows.bat) -
macOS: Run in terminal:
bash install_mac.command
-
Linux: Run in terminal:
bash install_linux.sh
-
-
Launch the GUI: After installation, simply run:
openlpt-gui
You can install OpenLPT directly from PyPI:
- For GUI Support (Recommended):
pip install "openlpt[gui]" - For CLI-only:
pip install "openlpt"
If you prefer to set up the environment manually:
-
Prerequisites:
-
Create Environment and Install:
# Create the environment from conda-forge, with requirements.txt's packages but its pip-only line # (Windows: findstr /V pip-only requirements.txt > req_conda.txt) grep -v pip-only requirements.txt > req_conda.txt conda create -n OpenLPT --override-channels -c conda-forge python=3.11 qt6-webengine --file req_conda.txt conda activate OpenLPT # The pip-only dependency, then build and install the package pip install "pycine>=0.3.2" pip install . --no-build-isolation
qt6-webengineshows the camera calibration's results page in its Report tab. conda-forge has none for Intel Macs: leave it out there, and the tab opens the page in the browser.- Windows: also add
pywin32 "libblas=*=*openblas"toconda create. conda-forge picks MKL for numpy there, with which numpy's linear algebra can crash the interpreter.
| Problem | Solution |
|---|---|
| Windows: Build fails | Install VS Build Tools and Win11 SDK |
macOS: omp.h not found |
See macOS OpenMP Fix section below |
| macOS: Architecture | python -c "import platform; print(platform.machine())" |
| Linux: Permissions | Use chmod +x or sudo |
| All: Stale cache | Delete build/ folder and retry |
| Installation: Build isolation | If compilation fails due to network, try pip install . --no-build-isolation |
If you get fatal error: 'omp.h' file not found:
export CC="$CONDA_PREFIX/bin/clang"
export CXX="$CONDA_PREFIX/bin/clang++"
export CPPFLAGS="-I$CONDA_PREFIX/include"
export LDFLAGS="-L$CONDA_PREFIX/lib -lomp"
pip install -e .Please see the sample format of configuration files, camera files and image files in /test/test_STB or /test/test_STB_Bubble.
To run the sample:
- Open OpenLPT GUI.
- Load the project configuration from the sample folders.
- Click 'Run tracking'.
Use openlpt preprocess to convert TIFF image lists, direct TIFF files, or Phantom CINE files into processed TIFF outputs plus OpenLPT image lists.
openlpt preprocess \
--input-root I:/VONSET/Data/20230123/T2 \
--frames 0 999--input-root auto-detects cameras in natural order. It first looks for CINE files in ROOT/Cam1/*.cine, ROOT/Cam2/*.cine, ... (case-insensitive directory names are fine), and also supports flat roots such as ROOT/cam1.cine, ROOT/cam2.cine. If --output-dir is omitted in this mode, output defaults to ROOT/imgFile.
openlpt preprocess \
--input-list cam1_images.txt \
--input-list cam2_images.txt \
--output-dir processed_tiffsopenlpt preprocess \
--input-root /scratch/run01 \
--frames 0 999 \
--background meanYou can still use direct --cine paths when needed:
openlpt preprocess \
--cine /scratch/cam1.cine \
--cine /scratch/cam2.cine \
--frames 0 999 \
--output-dir /scratch/preprocessed \
--background meanopenlpt preprocess \
--input-list cam1_images.txt \
--output-dir processed_tiffs \
--background mean \
--bg-count 50 \
--bg-stride 5 \
--invertopenlpt preprocess \
--input-list cam1_images.txt \
--input-list cam2_images.txt \
--output-dir processed_tiffs \
--workers 4Use --workers 0 to use all available CPU cores, which is convenient for cluster jobs:
openlpt preprocess \
--cine /scratch/cam1.cine \
--frames 0 999 \
--output-dir /scratch/preprocessed \
--workers 0Processed TIFFs are written under OUTPUT_DIR/camN/, and per-camera image lists are written as OUTPUT_DIR/camN_image_list.txt.
For --input-root, TIFF camera folders under the root are also auto-detected and processed in natural camera order. TIFF root mode currently expects per-camera subdirectories; flat TIFF roots are not auto-grouped.
In the GUI preprocessing panel, use Generate CLI below Process Image (Batch Export) to create a command from the current GUI settings. When all loaded CINE files share a common ROOT/CamN/ layout, the generated command prefers --input-root ROOT and uses ROOT/imgFile rather than imgFile_processed.
Note
CINE preprocessing requires pycine, which is listed in this repository's requirements.txt and pyproject.toml. The preprocessing CLI modules are headless/Qt-free, but some full-repository install routes also include GUI dependencies such as PySide6.
If you use OpenLPT in your research, please cite our publications:
- Tan, S., Salibindla, A., Masuk, A.U.M. and Ni, R., 2020. Introducing OpenLPT: new method of removing ghost particles and high-concentration particle shadow tracking. Experiments in Fluids, 61(2), p.47.
- Tan, S., Zhong, S. and Ni, R., 2023. 3D Lagrangian tracking of polydispersed bubbles at high image densities. Experiments in Fluids, 64(4), p.85.
- Zhong, S., Tan, S., Zhang, X., Li, Y. and Ni, R., 2026. A complete forward projection algorithm through cylindrical and spherical refractive windows. arXiv preprint arXiv:2610.17413.
This repository contains a mix of original code and MATLAB Coder-generated files under a MathWorks Academic License.
The following paths contain code generated by MATLAB Coder and are NOT covered by the general MIT/Open-source license of this repository:
/src/srcObject/BubbleCenterAndSizeByCircle/src/srcObject/BubbleCenterAndSizeByCircle/CircleIdentifier.cpp/src/srcObject/BubbleResize/inc/libObject/BubbleCenterAndSizeByCircle/inc/libObject/CircleIdentifier.h/inc/libObject/BubbleResize
For the paths listed above:
- ACADEMIC INTERNAL OPERATIONS ONLY: Usage is restricted to teaching, academic research, and course requirements.
- NO Commercial Use: Government, commercial, or other organizational use is NOT permitted.
- Header Preservation: Do not modify or remove the "Academic License" header comments in these files.
- No Sublicensing: These files are not sublicensed under this repository's open-source license.
- Redistribution: If you redistribute this repository, you must keep the original Academic License headers in the generated files.
- Modification: If you need to modify the generated code, you must hold a valid MathWorks MATLAB Coder license.
All other files in this repository are original work and are distributed under the MIT License (see LICENSE).
- Issues: Please report bugs or request features via GitHub Issues.
- Contact: For questions, please contact szhong12@jhu.edu or tanshiyong84@gmail.com.
- Organization: Ni Research Lab, Johns Hopkins University.
- Support: If you find this tool helpful, please give us a ⭐ on GitHub!

