nx_imgransac.nx
buildroot/runtime/nx_imgransac.nx
about
nx_imgransac.nx -- GEOMETRIC VERIFICATION by translation consensus (integer RANSAC).
Descriptor matching alone is not identity -- two images can share a handful of similar-looking
local patches by chance. What makes it identity is that the matched points AGREE ON ONE GEOMETRY:
if this is really the same picture, every true correspondence is explained by a single consistent
coordinate transform, and the chance matches are not. Counting how many matches obey one transform
(the INLIERS) is the signal; that inlier count is what separates "some patches rhymed" from "this
is the same image, cropped".
TRANSLATION MODEL, and why it is the RIGHT one for the classes we target rather than a shortcut:
nx_imgxform's crop is a sub-window COPY (pixels unchanged, coordinate origin shifted) and its
letterbox is a border PAD (pixels unchanged, coordinate origin shifted the other way). Both map an
original point (x,y) to a transformed point (x+dx, y+dy) under ONE offset. So the maximal set of
matches sharing an offset (within a pixel tolerance) is exactly the inlier set, and finding it is a
2-DOF consensus -- no float, no matrix, no iteration count to tune. Rotation and scale need the
affine/similarity extension (filed); the dihedral tier already owns the rotation axis globally.
This is a genuine RANSAC in the Fischler-Bolles sense: each match is a minimal hypothesis (one
point pair determines the translation), and we score every hypothesis by its consensus set. With
n <= KP_MAX matches the O(n^2) all-pairs evaluation is exhaustive, so it finds the global best
consensus deterministically -- no random sampling, no seed, bit-reproducible.
genealogy_id: fischler_bolles_1981_ransac (translation consensus). license_tier: ORIGINAL
dependencies 1 imports · 1 importers
imports: syscalls.nx
imported by: nx_imgsearch_tier.nx
structs
| none |
consts
| 25 | const RANSAC_TOL: i64 = 2 // pixel tolerance for a match to count as an inlier of a hypothesis |
| 63 | const RANSAC_SIM_TOL: i64 = 4 // base-pixel tolerance (scale amplifies error, so > translation tol) |
| 64 | const RANSAC_SIM_MINSPAN: i64 = 8 // minimal L1 span of the reference pair (small spans -> unstable s) |
| 65 | const RANSAC_SIM_SMIN: i64 = 128 // 0.5x in 1/256 units -- reject implausible scale estimates |
| 66 | const RANSAC_SIM_SMAX: i64 = 768 // 3.0x |
functions
| 27 | func rn_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } |
| 31 | func nx_imgransac_inliers(qx: *i64, qy: *i64, dx: *i64, dy: *i64, n: i64, out_off: *i64) -> i64 |
| 68 | func nx_imgransac_inliers_sim(qx: *i64, qy: *i64, dx: *i64, dy: *i64, n: i64, out_scale256: *i64) -> i64 |