WebARKitLib-rs is a high-performance, memory-safe Rust port of the WebARKitLib (originally C/C++).
This project aims to provide a pure-Rust implementation of the core ARToolKit algorithms, targeting both native systems and WebAssembly (WASM) for high-performance augmented reality in the browser.
Note
This project is currently a Work in Progress. Core marker detection and pose estimation are functional. KPM/NFT (Natural Feature Tracking) is in an early stage with partial Rust porting -- a fully idiomatic Rust KPM pipeline with a working example is the primary goal for v1.0.0.
- Pure Rust: Built for safety, speed, and modern concurrency. (crates.io)
- Dual WASM Strategy: Automated release of both Standard and SIMD binaries to maximize performance and compatibility.
- SIMD-Accelerated Pattern Matching: Uses
i16fixed-point arithmetic and WASMi32x4_dot_i16x8instructions for ultra-fast correlation matching. - Barcode Marker Support: Robust decoding for square matrix markers (3x3 to 6x6) with ECC.
- WASM Ready: High-performance tracking in the browser via WebAssembly. (@webarkit/webarkitlib-wasm)
- Side-Effect Free: Pure mathematical engine, easy to test and integrate.
- CI-Integrated Benchmarking: Performance parity with original C implementation.
- SIMD-Accelerated Pattern Matching: Uses
i16fixed-point arithmetic for the core correlation loops, leveraging WASMi32x4_dot_i16x8instructions for significant speedups. - Numerical Parity: Our SIMD and Scalar paths are calibrated to produce bit-identical results (including rounding logic in grayscale and thresholding), ensuring deterministic behavior across all devices.
- Sub-millisecond Tracking: Core detection loop is optimized for sub-millisecond execution on standard ARM/x86 hardware.
Add webarkitlib-rs to your Cargo.toml:
[dependencies]
webarkitlib-rs = "0.3"To enable the C++ FFI backend for KPM (Natural Feature Tracking):
[dependencies]
webarkitlib-rs = { version = "0.3", features = ["ffi-backend"] }When installing from crates.io, no extra setup is required β the C++ sources needed by
ffi-backendship inside the published crate.
This repository uses a git submodule for the WebARKitLib C++ sources that
back the ffi-backend feature. Clone recursively:
git clone --recursive https://github.com/webarkit/WebARKitLib-rs.gitIf you already cloned without --recursive:
git submodule update --init --recursiveThe submodule lives at crates/core/third_party/WebARKitLib and is pinned
to a specific upstream commit. Building from a non-recursive clone will
fail early in build.rs with an actionable message.
To see the marker detection in action on your local machine, run the provided simple example:
cargo run --example simpleThis example loads a camera parameter file, a marker (pattern or barcode), and a sample image, performing detection and outputting the 3D pose extrinsics.
Generate NFT (Natural Feature Tracking) marker files compatible with ARnft and NFT-Marker-Creator-App:
# Basic usage (requires C++ FREAK backend for .fset3):
cargo run --release --features ffi-backend --example nft_marker_gen -- \
--input path/to/image.jpg \
--output path/to/output_name \
--dpi 220
# With SIMD acceleration + Rayon parallelism (recommended for x86_64):
cargo run --release --features "ffi-backend,simd-x86-sse41,simd-x86-avx2" \
--example nft_marker_gen -- \
--input path/to/image.jpg \
--output path/to/output_name \
--dpi 220Important: Always use the
--releaseflag. Debug builds are 5β10Γ slower due to missing compiler optimizations.
This produces three files:
output_name.isetβ JPEG-compressed image pyramid (~300 KB, matches C++ar2WriteImageSet()format)output_name.fsetβ Feature map with one entry per pyramid leveloutput_name.fset3β FREAK descriptors for KPM-based recognition
Options:
| Flag | Long form | Description | Default |
|---|---|---|---|
-i |
--input |
Path to the source image (JPEG/PNG) | required |
-o |
--output |
Output base path (without extension) | required |
-d |
--dpi |
Source image resolution in DPI | required |
-l |
--level |
Tracking extraction level (0β4) | 2 |
-n |
--search-feature-num |
Max features per pyramid level | 250 |
Performance feature flags:
| Feature flag | What it enables |
|---|---|
ffi-backend |
C++ FREAK backend for .fset3 generation (required for full NFT markers) |
simd-x86-sse41 |
SSE4.1 SIMD acceleration for feature map correlation (get_similarity) |
simd-x86-avx2 |
AVX2+FMA SIMD acceleration for feature map correlation (faster than SSE4.1) |
simd |
Umbrella flag β enables all SIMD optimizations (SSE4.1, AVX2, WASM SIMD, image, pattern) |
Rayon-based parallelism is always enabled (no feature flag needed): pyramid level generation and Stage-3 feature scoring run in parallel across CPU cores.
A unified, parameterized barcode example is available for testing all supported matrix code types:
# Default: 3x3 matrix code type, auto-sweeps threshold 60β180
cargo run --example barcode
# Specify a matrix code type (e.g. 4x4) and supply the matching marker image
cargo run --example barcode -- -m 4x4 -i crates/core/examples/Data/marker_07_4x4.jpg
# Use a fixed threshold instead of auto-sweeping
cargo run --example barcode -- -m 3x3 -t 100
# Full example: type, threshold, and custom image path
cargo run --example barcode -- -m 5x5 -t 120 -i path/to/marker.jpgOptions:
| Flag | Long form | Description | Default |
|---|---|---|---|
-m |
--matrix-code-type |
Matrix code type (3x3, 3x3parity65, 3x3hamming63, 4x4, 4x4bch1393, 4x4bch1355, 5x5, 5x5bch22125, 5x5bch2277, 6x6) |
3x3 |
-t |
--threshold |
Fixed labeling threshold (0β255). When omitted, sweeps 60β180 in steps of 20 | (auto-sweep) |
-i |
--image |
Path to the input image | bundled 3x3 marker image |
The WASM port allows you to run the AR engine directly in most modern browsers.
For integration into your own project, install the pre-built package from npm β no local build required:
npm install @webarkit/webarkitlib-wasmSee @webarkit/webarkitlib-wasm for API documentation and usage examples.
The crates/wasm/www folder contains interactive web demos. To run them you need to build the WASM modules locally:
-
Build the modules (generates both Standard and SIMD bundles):
npm run build:wasm
Alternatively, download the pre-built
wasm-packageartifact from the latest CI run and extract its contents intocrates/wasm/pkg/. -
Serve the demo:
cd crates/wasm/www npx serve .
simple.htmlβ static image demo with engine selector and threshold visualization.simple_video_marker_example.htmlβ live webcam demo with engine selector, marker type (pattern/barcode) selector, and threshold slider.
WebARKitLib-rs uses the standard log crate facade, with ARToolKit-style macros (arlog_d!, arlog_i!, arlog_w!, arlog_e!, arlog_rel!, arlog_perror!) that mirror the C ARLOG* API:
| C macro | Rust macro |
|---|---|
ARLOGd("x=%d", x); |
arlog_d!("x={}", x); |
ARLOGi("x=%d", x); |
arlog_i!("x={}", x); |
ARLOGw("x=%d", x); |
arlog_w!("x={}", x); |
ARLOGe("x=%d", x); |
arlog_e!("x={}", x); |
ARLOG("banner\n"); |
arlog_rel!("banner"); |
ARLOGperror("open"); |
arlog_perror!("open"); |
Enable the log-helpers feature and call the bundled initializer once in your binary:
[dependencies]
webarkitlib-rs = { version = "0.3", features = ["log-helpers"] }fn main() {
webarkitlib_rs::arlog::ar_log_init_default();
// ... your application
}Produces [info] ..., [warning] ..., [error] ..., [debug] ... β matching the C output exactly. Release-info messages (arlog_rel!) print unprefixed.
For richer output (timestamp + originating module), use the verbose initializer:
fn main() {
webarkitlib_rs::arlog::ar_log_init_default_verbose();
// ... your application
}Produces a single bracketed header per line:
[info - 2026-04-21T14:23:45Z - webarkitlib_rs::marker] hello
[warning - 2026-04-21T14:23:45Z - webarkitlib_rs::ar2] low mem
[error - 2026-04-21T14:23:45Z - webarkitlib_rs::kpm] bad fd
Filtering still respects RUST_LOG; only the formatting changes. arlog_rel! messages stay prefix-free in verbose mode too. On wasm32, use ar_log_init_wasm_verbose(), which raises the level to Debug (browser DevTools renders the timestamp and source location natively).
Set via environment variable (honored by the default helper):
RUST_LOG=debug cargo run --example simpleOr programmatically:
use webarkitlib_rs::arlog::{set_ar_log_level, ArLogLevel};
set_ar_log_level(ArLogLevel::Debug);Because it's the log crate facade, any compatible backend works:
- WASM / browser β
console_log(or the bundledar_log_init_wasm()helper under thelog-helpersfeature) - Android β
android_logger - Apple (iOS/macOS) β
oslog - Structured / OpenTelemetry β
tracing+tracing-log
No library code change is needed β pick the backend in your application's entry point.
We maintain a strict performance comparison with the original C library to ensure our Rust port remains competitive.
Detailed SIMD performance results and reproduction steps can be found in the BENCHMARKS.md file.
-
Bootstrap the C library:
cd benchmarks/c_benchmark python ../bootstrap.py --bootstrap-file libraries.jsonNote: this Python bootstrap is only required for the standalone C benchmark build here. The Rust
ffi-backendfeature gets its C++ sources from the git submodule atcrates/core/third_party/WebARKitLiband does not require Python. -
Execute the Suite:
# Rust Benchmark cargo bench -p webarkitlib-rs --bench marker_bench # C Benchmark (Manual build required once) cd benchmarks/c_benchmark/build cmake --build . --config Release ./c_benchmark ../../data/camera_para.dat ../../data/patt.hiro ../../data/hiro.raw 429 317
We use criterion to track performance over time. You can save specific snapshots as "baselines":
# Save a milestone baseline
cargo bench -- --save-baseline milestone-20260307The workspace contains two crates:
crates/core(webarkitlib-rs): The unified core AR engine (pure Rust), including:ar2module: NFT marker generation pipeline β image pyramid (ar2_gen_image_set), feature map (ar2_gen_feature_map), JPEG-compressed.isetsave,.fset/.fset3I/O.kpmmodule: Keypoint Matching with pluggable backends (Rust + C++ FFI), FREAK descriptor extraction.- Core modules: image processing, pattern matching, labeling, ICP, pose estimation.
crates/wasm(webarkitlib-wasm): WASM bindings, dual-build scripts, and diagnostic web demo.benchmarks: C vs Rust performance comparison suite.ARCHITECTURE.md: Detailed technical overview of the library's design and SIMD optimizations.
- M1 -- KPM/NFT Core (partial): Ported the initial KPM (Keypoint Matching) scaffolding -- binary feature types, matching orchestration, ICP-based pose refinement, and
.fset3/.iset/.fsetI/O. The C++ FreakMatcher FFI backend works but the full pipeline is not yet wired end-to-end. - M2 -- AR2 I/O: Ported AR2 image set (
.iset) and feature set (.fset) binary I/O from C to Rust. - M3 -- Architectural Consolidation: Unified the workspace from 4 crates down to 2 (
webarkitlib-rs+webarkitlib-wasm), with KPM and AR2 as submodules of the core crate. - M4 -- Working NFT Marker Generator: End-to-end
nft_marker_genexample producing.iset/.fset/.fset3files fully compatible with ARnft and NFT-Marker-Creator-App, including:- JPEG-compressed
.isetsave matching C++ar2WriteImageSet()format (~300 KB vs ~10 MB raw) - All pyramid levels included in
.fset(including 0-feature levels), matching C++ output exactly - FREAK descriptor extraction via
kpm_extract_featuresC API (7000+ features per marker) - Detailed step-by-step logging with timestamps and per-level statistics
- JPEG-compressed
- M5 -- NFT Pipeline Performance: Rayon parallelism for pyramid generation and Stage-3 feature scoring, plus optional SSE4.1/AVX2+FMA SIMD vectorization of the
get_similaritycorrelation kernel. ~1.7Γ total speedup on x86_64.
- Complete KPM in idiomatic Rust: Port the remaining KPM feature extraction and matching logic to pure Rust, removing the C++ FFI dependency, and ship a working end-to-end NFT example.
- Enhanced Documentation: Expand API reference with complete module-level docs, integration walkthroughs for JS/TS, and detailed usage examples.
- WASM Memory Management: Improve resource cleanup when switching engines or markers in long-running browser sessions.
- Multi-Marker Support: Port
arMultilogic to enable tracking of multiple markers simultaneously. - Advanced Video Abstraction: Develop a cross-platform video handling layer to simplify integration with various input sources.
This project is a port of the excellent WebARKitLib project. Special thanks to the original ARToolKit contributors.
This project is licensed under the LGPLv3 License - see the LICENSE file for details.
