Skip to content

v1.4.5: LoFTR input padded to its coarse stride, max_features caps BRISK, KAZE and AKAZE - #12

Merged
rfonod merged 4 commits into
mainfrom
v1.4.5-dev
Oct 22, 2026
Merged

rfonod merged 4 commits into
mainfrom
v1.4.5-dev

Conversation

@rfonod

@rfonod rfonod commented Oct 22, 2026

Copy link
Copy Markdown
Owner

Summary

Two fixes to the feature detectors, both of which made a configured value mean something other than what it says.

  • LoFTR input is padded to a multiple of 8. kornia's LoFTR matches on a coarse grid of stride 8 and maps grid cells back to pixels with the ratio of the input height to the coarse height. When a side of the processed frame is not a multiple of 8 that ratio is not 8, so every match carried an error proportional to its distance from the origin. _LoFTRMatcher.match now zero-pads both images at the bottom and right (new dl.pad_to_multiple, which leaves pixel coordinates unchanged) and drops matches that fall in the padding.
  • max_features caps BRISK, KAZE and AKAZE. These detectors take a response threshold, not a count, and stabilo converted max_features into one with linear models fitted at native resolution (stabilo/thresholds/models/). The models ignored downsample_ratio, and AKAZE's went negative above about 11k keypoints, so the reference frame kept every keypoint. The detectors now run at their own threshold (brisk_threshold, kaze_threshold, akaze_threshold) and keep the max_features strongest by response (ref_multiplier x max_features in the reference frame), as ORB and SIFT already do. The thresholds default to OpenCV's (30, 0.001, 0.001); they were previously fallbacks that the shipped models made unreachable.

Output impact

  • LoFTR: unchanged when both sides of the processed frame are multiples of 8 (no padding is applied). Otherwise the bias is removed. On a 4K aerial frame warped by a known homography, the mean corner error drops from 22.3 to 0.33 px at downsample_ratio 0.18 (691x389) and from 7.9 to 0.16 px at 0.25 (960x540).
  • BRISK, KAZE, AKAZE: keypoint counts and homographies change. Reference/current keypoints on a 4K pair:
Setting Detector v1.4.4 v1.4.5
0.18 / 2000 BRISK 225 / 137 4000 / 2000
0.18 / 2000 AKAZE 70 / 40 1149 / 1171
1.0 / 8000 BRISK 26,706 / 6289 16,000 / 8000
1.0 / 8000 AKAZE 228,234 / 7471 16,000 / 8000
  • ORB, SIFT, RootSIFT and the sparse learned detectors: unchanged. The default-path regression test passes.

Tests

  • 12 cases for the cap: at most max_features / ref_multiplier x max_features at two downsample ratios, the kept keypoints and descriptors equal the uncapped detector's strongest, and a cap above the detected count keeps every keypoint.
  • 4 offline cases for the padding (a stand-in LoFTR records the padded shapes and returns a match in the padding), and 2 end-to-end LoFTR cases recovering a known homography at sizes not divisible by 8.
  • With the fixes reverted, 16 of the 18 new cases fail.
  • Full suite: 205 passed, 18 skipped (CUDA and DL end-to-end); with STABILO_DL_TESTS=1, all 40 DL tests pass. stabilo CLI smoke test passes; the wheel and sdist build and pass twine check.

Docs

  • docs/usage.md section 9 describes the cap for every classical detector and the LoFTR padding; the parameter table lists the new threshold defaults.
  • stabilo/cfg/default.yaml, the README feature list and scripts/README.md no longer describe the threshold models as the source of the budget. scripts/find_threshold_models.py stays as a tool for choosing a threshold.

Other

  • stabilo/thresholds/models/ is removed from the package; package-data now ships **/*.yaml only.
  • Version bumped to 1.4.5 in __init__.py, CITATION.cff, .zenodo.json, and the README citation.

@rfonod
rfonod merged commit 5d72168 into main Oct 22, 2026
10 checks passed
@rfonod
rfonod deleted the v1.4.5-dev branch October 22, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant