You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Umbrella / roadmap issue. Captures the architecture and the full feature set for building a WebAR solution on top of jsfeatNext, from the "Libreria realtà aumentata con jsfeatNext" design discussion. Individual components will spin off into their own issues (in a dedicated high-level AR repo once it exists).
Goal
Natural-feature-tracking WebAR for planar (image) targets — the classic ARToolKit-NFT / Vuforia-image-target use case: detect a reference image in the camera feed and anchor a 3D object on it. (Not full SLAM, not arbitrary surfaces.)
Two-layer architecture
The decision from the discussion: jsfeatNext stays a generic, stateless image-processing / CV library. Everything stateful and AR-specific lives in a separate high-level, stateful AR project (TypeScript), which talks to the CV backend only through the minimum CvBackend interface (#96).
┌─────────────────────────────────────────────────────────────┐
│ High-level AR project — TypeScript, STATEFUL │
│ target training · tracking loop · pose refinement · │
│ geometric validation · temporal filter · renderer adapters │
└───────────────────────────┬─────────────────────────────────┘
│ CvBackend interface (#96)
│ detect · describe · match ·
│ estimateHomography · poseFromHomography
┌───────────────┬───────────────┬──────────────┬──────────────┐
standard WASM WebARKitLib jsartoolkitNFT
(jsfeatNext) (PureCV) (OpenCV/WASM) (KPM/WASM)
pure TS/JS Rust→WASM ← already ← future candidate
portable fast implements (needs rewrite)
this pipeline
The layer is backend-agnostic and "elastic": pick standard (jsfeatNext), WASM (PureCV), or — with the rewrite noted in #96 — WebARKitLib / jsartoolkitNFT, all behind the same contract.
Readiness map (state of the code)
✅ In jsfeatNext (stateless CV primitives) — the vision half is essentially done:
⭐ Prior art: WebARKitLib already implements this pipeline (OpenCV/WASM)
Important context — the high-level layer is NOT green-field.WebARKitLib (C++ → emscripten/WASM, driven by webarkit-testing, an emscripten port of artoolkitX's OCVT planar-tracking design) is a working implementation of exactly this pipeline, built on OpenCV:
Detection/description:cv::ORB and cv::AKAZE
Matching:cv::BFMatcher
Tracking loop:cv::calcOpticalFlowPyrLK + TrackingPointSelector — i.e. the tracker_t detect↔track↔recover machinery already exists there
Homography:WebARKitHomographyInfo
Renderer adapters:getPoseMatrixGL() and getCameraProjectionMatrix() — the modelViewGL/projectionGL equivalents, already solved
JS side:webarkit-testing's WebARKitController.js (init_raw() / process_raw(), getMarker event, pose/matrix getters) is a real high-level controller
What this means for this roadmap: every component below should be designed with WebARKitLib as the reference, not invented from scratch — it is the proven design (and a numeric/behavioural comparison target). The open question is not how to build a planar tracker, but how to factor it so the same orchestration works over a pluggable backend (#96) instead of being fused to one CV implementation.
As a granular CvBackend — needs the "valuable rewrite" to expose primitives individually (its public API is processFrameData() → pose, a bundled pipeline).
As a whole-pipeline tracker — it could satisfy a coarser TrackerBackend seam (frame in → pose out) as-is, with no rewrite, letting the high-level layer delegate wholesale instead of composing primitives. Worth evaluating before writing tracker_t from zero.
🔴 To build — the high-level AR layer (this roadmap):
Target training — pattern_t. Reference image (+ its real dimensions) → reusable multi-scale descriptor set with associated model-plane coordinates. Today this is throwaway inline code in the sample; needed to make "targets" first-class objects.
Tracking loop — tracker_t ⭐ the real bottleneck. A detect → track → recover state machine: once the target is locked, don't re-run ORB every frame — follow the inlier points frame-to-frame with optical_flow_lk and re-estimate the homography from the tracked points; only re-run the heavy detection when tracking is lost or confidence drops. This is what turns a stuttering demo into a 30–60 fps tracker (likely why the sample "didn't work well"). All the bricks exist (optical_flow_lk, pyramid_t, motion_estimator) — the orchestration is what's missing.
Renderer adapters — modelViewGL + projectionGL.modelViewGL(pose): column-major 4×4 for three.js/WebGL, CV→GL via diag(1,-1,-1). projectionGL(K, w, h, near, far): the GL projection consistent with the same intrinsics K — without it, even a perfect pose won't line up. These are rendering glue, so they live here, not in jsfeatNext (keeps the CV lib renderer-agnostic). (Moved out of jsfeatNext scope — see the Add bfmatcher and pose_estimator modules to complete the natural-feature AR pipeline #83 correction.)
Pose refinement. Non-linear minimization of reprojection error (small Gauss-Newton / Levenberg-Marquardt); linalg gives the algebra, the solver is missing.
Temporal filter. Smooth the pose across frames to kill jitter.
Undistort (accuracy). Apply known distortion coefficients (could be an imgproc helper in jsfeatNext, or high-level). Full calibration is done offline; pose_estimator.intrinsics() bootstraps without it.
⚪ App layer (out of the library entirely): camera capture (getUserMedia → canvas → RGBA), the engine loop stitching capture → CV → pose → rendering, and the three.js bridge. Running the CV pipeline in a WebWorker keeps the main thread free — and heavy frames are exactly where the WASM (PureCV) backend beats pure JS.
Open question worth settling early
Given WebARKitLib already works: is the goal (a) a new TS orchestration layer that can drive any backend — with jsfeatNext as the portable no-WASM option and WebARKitLib/PureCV as the fast ones — or (b) jsfeatNext-based AR specifically, as a dependency-free alternative to the WASM stack? The components below are the same either way, but it changes whether tracker_t is written fresh or wraps an existing tracker.
Suggested sequencing
pattern_t (target training) + projectionGL — closes the end-to-end loop so you can see something anchored.
tracker_t — the detect↔track↔recover loop; the single biggest lever from "demo" to "usable".
Then robustness: geometric validation → temporal filter → pose refinement.
Goal
Natural-feature-tracking WebAR for planar (image) targets — the classic ARToolKit-NFT / Vuforia-image-target use case: detect a reference image in the camera feed and anchor a 3D object on it. (Not full SLAM, not arbitrary surfaces.)
Two-layer architecture
The decision from the discussion: jsfeatNext stays a generic, stateless image-processing / CV library. Everything stateful and AR-specific lives in a separate high-level, stateful AR project (TypeScript), which talks to the CV backend only through the minimum
CvBackendinterface (#96).The layer is backend-agnostic and "elastic": pick standard (jsfeatNext), WASM (PureCV), or — with the rewrite noted in #96 — WebARKitLib / jsartoolkitNFT, all behind the same contract.
Readiness map (state of the code)
✅ In jsfeatNext (stateless CV primitives) — the vision half is essentially done:
imgproc,pyramid_t)fast_corners,yape,yape06)orb.describe)homography2d,motion_estimator)optical_flow_lk) — the building block for frame-to-frame tracking🟡 Prototyped (promote to jsfeatNext modules) — tracked in #83:
bfmatcher— brute-force Hamming matcher (was inline insample_orb_pinball.html)pose_estimator—H → (R, t)planar pose decomposition (camera frame only)⭐ Prior art: WebARKitLib already implements this pipeline (OpenCV/WASM)
Important context — the high-level layer is NOT green-field. WebARKitLib (C++ → emscripten/WASM, driven by webarkit-testing, an emscripten port of artoolkitX's OCVT planar-tracking design) is a working implementation of exactly this pipeline, built on OpenCV:
cv::ORBandcv::AKAZEcv::BFMatchercv::calcOpticalFlowPyrLK+TrackingPointSelector— i.e. thetracker_tdetect↔track↔recover machinery already exists thereWebARKitHomographyInfogetPoseMatrixGL()andgetCameraProjectionMatrix()— themodelViewGL/projectionGLequivalents, already solvedwebarkit-testing'sWebARKitController.js(init_raw()/process_raw(),getMarkerevent, pose/matrix getters) is a real high-level controllerWhat this means for this roadmap: every component below should be designed with WebARKitLib as the reference, not invented from scratch — it is the proven design (and a numeric/behavioural comparison target). The open question is not how to build a planar tracker, but how to factor it so the same orchestration works over a pluggable backend (#96) instead of being fused to one CV implementation.
It also plugs into #96 in two distinct ways:
CvBackend— needs the "valuable rewrite" to expose primitives individually (its public API isprocessFrameData()→ pose, a bundled pipeline).TrackerBackendseam (frame in → pose out) as-is, with no rewrite, letting the high-level layer delegate wholesale instead of composing primitives. Worth evaluating before writingtracker_tfrom zero.🔴 To build — the high-level AR layer (this roadmap):
pattern_t. Reference image (+ its real dimensions) → reusable multi-scale descriptor set with associated model-plane coordinates. Today this is throwaway inline code in the sample; needed to make "targets" first-class objects.tracker_t⭐ the real bottleneck. Adetect → track → recoverstate machine: once the target is locked, don't re-run ORB every frame — follow the inlier points frame-to-frame withoptical_flow_lkand re-estimate the homography from the tracked points; only re-run the heavy detection when tracking is lost or confidence drops. This is what turns a stuttering demo into a 30–60 fps tracker (likely why the sample "didn't work well"). All the bricks exist (optical_flow_lk,pyramid_t,motion_estimator) — the orchestration is what's missing.modelViewGL+projectionGL.modelViewGL(pose): column-major 4×4 for three.js/WebGL, CV→GL viadiag(1,-1,-1).projectionGL(K, w, h, near, far): the GL projection consistent with the same intrinsicsK— without it, even a perfect pose won't line up. These are rendering glue, so they live here, not in jsfeatNext (keeps the CV lib renderer-agnostic). (Moved out of jsfeatNext scope — see the Addbfmatcherandpose_estimatormodules to complete the natural-feature AR pipeline #83 correction.)linalggives the algebra, the solver is missing.imgprochelper in jsfeatNext, or high-level). Full calibration is done offline;pose_estimator.intrinsics()bootstraps without it.⚪ App layer (out of the library entirely): camera capture (
getUserMedia→ canvas → RGBA), the engine loop stitching capture → CV → pose → rendering, and the three.js bridge. Running the CV pipeline in a WebWorker keeps the main thread free — and heavy frames are exactly where the WASM (PureCV) backend beats pure JS.Open question worth settling early
Given WebARKitLib already works: is the goal (a) a new TS orchestration layer that can drive any backend — with jsfeatNext as the portable no-WASM option and WebARKitLib/PureCV as the fast ones — or (b) jsfeatNext-based AR specifically, as a dependency-free alternative to the WASM stack? The components below are the same either way, but it changes whether
tracker_tis written fresh or wraps an existing tracker.Suggested sequencing
pattern_t(target training) +projectionGL— closes the end-to-end loop so you can see something anchored.tracker_t— the detect↔track↔recover loop; the single biggest lever from "demo" to "usable".What stays in jsfeatNext vs here
bfmatcher,pose (R,t), detect/ORB,estimateHomography(#83, #96)pattern_t,tracker_t, pose refinement, geometric validation, temporal filter, renderer adapters (modelViewGL,projectionGL)Non-goals
Related
CvBackendinterface (pluggable, stateless CV contract for a high-level WebAR layer) #96bfmatcherandpose_estimatormodules to complete the natural-feature AR pipeline #83