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
Update (2026-08-24): The overshoot on the right side was confirmed to be caused by a bad printed target image (shrunk/squished aspect ratio, e.g., via A4 "Fit to Page" print settings), which is the same problem documented in webarkit/WebARKitLib-rs#240. Testing with the original "pinball" image displayed directly on a smartphone screen (at a 1:1 pixel aspect ratio) worked perfectly as expected. Thus, the overshoot is not caused by a "homography estimation error" or a code bug in jsfeatNext. The suggested changes in #134 (GMS) are not required to address this overshoot, though they may still improve overall tracking quality.
Summary
In examples/sample_orb_pinball.html the green quad drawn over the tracked marker follows the left, top and bottom edges of the physical target closely, but overshoots on the right. Reported from visual inspection, estimated at "up to ~10%, possibly less" — this is an eyeball figure, not a measurement.
Investigating it turned up two real defects in the example's training code. Both are genuine and worth fixing, but together they account for well under 1%, so they do not explain the observed overshoot. Filing everything found so the next person does not have to re-derive it.
Defect 1 — the outline is drawn one pixel narrower than the pattern frame
render_pattern_shape reconstructs the pattern size from the preview:
409 >> 1 = 204, and 204 * 2 = 408. The homography's coordinate frame is lev0_img, which is 409 wide, so the right edge is drawn 1 px short — about 0.25%, and in the opposite direction to the reported overshoot.
The round-trip only survives even dimensions. Drawing from lev0_img.cols/rows (or storing the trained size explicitly) removes the issue entirely.
Defect 2 — level coordinates are un-scaled by the requested scale, not the achieved one
In the per-level loop the image is resized with a truncated target:
but the detected keypoints are mapped back with the requested scale:
lev_corners[i].x*=1./sc;lev_corners[i].y*=1./sc;
The achieved scale is new_width / lev0_img.cols, which after | 0 is not sc. Measured for this pattern (409 × 512, sc_inc = sqrt(2), 4 levels):
lev
requested sc
resized to
effective x
effective y
x error
y error
1
0.70711
289 × 362
0.70660
0.70703
+0.072%
+0.011%
2
0.50000
204 × 255
0.49878
0.49805
+0.245%
+0.392%
3
0.35355
144 × 181
0.35208
0.35352
+0.419%
+0.011%
Two things worth noting:
The error is axis-asymmetric and non-monotonic, because it depends on how each dimension happens to truncate. 512 is a power of two and usually truncates cleanly; 409 is odd and does not.
At level 2 the height loses a whole pixel: sc is accumulated as sc /= sc_inc, so after two divisions by sqrt(2) it holds 0.4999999999999999, not 0.5. (512 * 0.4999999999999999) | 0 is 255, not 256. Recomputing sc as Math.pow(sc_inc, -lev) — or deriving the un-scale factor from lev_img.cols / lev0_img.cols — avoids this.
These feed slightly wrong keypoint coordinates into the homography fit, so they degrade the estimate rather than shifting the outline directly.
What is probably causing the visible overshoot
Neither defect above reaches 1%, so the observed error is most likely homography estimation error, not a drawing bug.
In the reported session the ORB matches are heavily concentrated on the left and centre of the target — the bright, high-contrast pinball artwork — while the right portion is darker and more foreshortened, contributing very few correspondences. A homography fitted from correspondences clustered on one side extrapolates least accurately on the opposite side, which is exactly where the error appears.
Attempted diagnostic: hold the target flat and fronto-parallel and see whether the overshoot changes. Result inconclusive — no obvious change was observed, but holding a hand-held print flat enough for this to be decisive is difficult, so this neither confirms nor rules out the hypothesis.
If this is the cause, the effective fix is not in this example: it is #134 (GMS), which filters geometrically inconsistent matches before find_homography and directly targets a poor inlier distribution. That is the natural time to revisit this.
Suggested scope
Draw the outline from the trained pattern dimensions rather than pattern_preview.cols * 2
Un-scale level coordinates by the achieved scale (lev_img.cols / lev0_img.cols) instead of the requested sc
Compute sc per level as a power rather than by repeated division, to stop float drift crossing an integer boundary
Re-assess the residual overshoot once feat(gms): grid-based motion statistics match filter #134 lands, before assuming anything further is wrong here (Update: confirmed to be a printed aspect ratio issue, see update note at the top)
examples/sample_orb.html shares the same training code and is presumably affected identically.
Low priority. Nothing here blocks the library itself — the defects are in example code, and the dominant term is most likely estimation quality rather than a bug.
Note
Update (2026-08-24): The overshoot on the right side was confirmed to be caused by a bad printed target image (shrunk/squished aspect ratio, e.g., via A4 "Fit to Page" print settings), which is the same problem documented in webarkit/WebARKitLib-rs#240. Testing with the original "pinball" image displayed directly on a smartphone screen (at a 1:1 pixel aspect ratio) worked perfectly as expected. Thus, the overshoot is not caused by a "homography estimation error" or a code bug in
jsfeatNext. The suggested changes in #134 (GMS) are not required to address this overshoot, though they may still improve overall tracking quality.Summary
In
examples/sample_orb_pinball.htmlthe green quad drawn over the tracked marker follows the left, top and bottom edges of the physical target closely, but overshoots on the right. Reported from visual inspection, estimated at "up to ~10%, possibly less" — this is an eyeball figure, not a measurement.Investigating it turned up two real defects in the example's training code. Both are genuine and worth fixing, but together they account for well under 1%, so they do not explain the observed overshoot. Filing everything found so the next person does not have to re-derive it.
Defect 1 — the outline is drawn one pixel narrower than the pattern frame
render_pattern_shapereconstructs the pattern size from the preview:and the preview is built by halving with
>>:For
img/pinball.jpg(1637 × 2048):sc0 = min(512/1637, 512/2048)0.25new_width,new_height409,512pattern_preview204 × 256408×512409 >> 1 = 204, and204 * 2 = 408. The homography's coordinate frame islev0_img, which is 409 wide, so the right edge is drawn 1 px short — about 0.25%, and in the opposite direction to the reported overshoot.The round-trip only survives even dimensions. Drawing from
lev0_img.cols/rows(or storing the trained size explicitly) removes the issue entirely.Defect 2 — level coordinates are un-scaled by the requested scale, not the achieved one
In the per-level loop the image is resized with a truncated target:
but the detected keypoints are mapped back with the requested scale:
The achieved scale is
new_width / lev0_img.cols, which after| 0is notsc. Measured for this pattern (409 × 512,sc_inc = sqrt(2), 4 levels):scTwo things worth noting:
scis accumulated assc /= sc_inc, so after two divisions bysqrt(2)it holds0.4999999999999999, not0.5.(512 * 0.4999999999999999) | 0is 255, not 256. RecomputingscasMath.pow(sc_inc, -lev)— or deriving the un-scale factor fromlev_img.cols / lev0_img.cols— avoids this.These feed slightly wrong keypoint coordinates into the homography fit, so they degrade the estimate rather than shifting the outline directly.
What is probably causing the visible overshoot
Neither defect above reaches 1%, so the observed error is most likely homography estimation error, not a drawing bug.
In the reported session the ORB matches are heavily concentrated on the left and centre of the target — the bright, high-contrast pinball artwork — while the right portion is darker and more foreshortened, contributing very few correspondences. A homography fitted from correspondences clustered on one side extrapolates least accurately on the opposite side, which is exactly where the error appears.
Attempted diagnostic: hold the target flat and fronto-parallel and see whether the overshoot changes. Result inconclusive — no obvious change was observed, but holding a hand-held print flat enough for this to be decisive is difficult, so this neither confirms nor rules out the hypothesis.
If this is the cause, the effective fix is not in this example: it is #134 (GMS), which filters geometrically inconsistent matches before
find_homographyand directly targets a poor inlier distribution. That is the natural time to revisit this.Suggested scope
pattern_preview.cols * 2lev_img.cols / lev0_img.cols) instead of the requestedscscper level as a power rather than by repeated division, to stop float drift crossing an integer boundaryNotes
examples/sample_orb.htmlshares the same training code and is presumably affected identically.