code wiki / (root) / nx_imgsearch_tier.nx

nx_imgsearch_tier.nx

buildroot/runtime/nx_imgsearch_tier.nx

21342 B370 linesdepth 7pulls 15 transitivereach 4 importersview sourcekind librarytopic imgsearch
docsdependenciesstructsconstsfunctions

about

nx_imgsearch_tier.nx -- THE REVERSE-IMAGE TIER BASE CLASS (vtable OOP). A production reverse-image engine is never ONE matcher. TinEye is a copy-detector; Google Lens is a semantic recogniser; Yandex fuses both plus faces and text. Our own ruler (nx_imgbench) proves why: no single descriptor covers the modification space -- dHash owns photometric edits and is blind to geometry, the edge-orientation descriptor owns crops and is blind to mirroring, and neither knows what the picture is OF. So the engine is defined as a FUSION OF TIERS, and a tier is an object with a vtable. Adding the next rung -- local keypoints + geometric verification, or a quantised semantic embedding -- is implemented as a NEW SUBTYPE with its own constructor. It is never an edit to the query engine. That is the whole point of the base class: the engine below it must not grow an `if` per rung. ASYMMETRIC DESCRIPTORS, deliberately. A tier declares TWO widths: idx_dim -- i64 slots persisted per corpus image (storage cost, multiplied by 10^8 images) qry_dim -- i64 slots computed per query (compute cost, paid once per search) They differ for good reasons. The dihedral tier stores ONE fingerprint but computes EIGHT at query time, buying full mirror/rotation invariance for zero storage. A future local-feature tier will store a compact bag-of-visual-words vector but compute a full keypoint set per query. Forcing both sides to one width would have taxed every stored image to pay for a query-side trick. Distances are INTEGER and each tier publishes max_dist, so scores are comparable across tiers without floats -- the same integer-quantisation discipline the text engine rides. license_tier: ORIGINAL

dependencies 5 imports · 1 importers

nx_phash.nx nx_visdesc.nx nx_imgorient.nx nx_imgkp.nx nx_imgransac.nx nx_imgsearch_tier.nx nx_imgsearch_engine.nx

imports: nx_phash.nxnx_visdesc.nxnx_imgorient.nxnx_imgkp.nxnx_imgransac.nx

imported by: nx_imgsearch_engine.nx

structs

99struct nx_imgtier

consts

31const NX_IT_KIND_COPY: i64 = 1 // near-duplicate: dHash Hamming (TinEye-class copy detection)
32const NX_IT_KIND_ORIENT: i64 = 2 // dihedral-invariant dHash (mirrors + quarter turns)
33const NX_IT_KIND_SIMILAR: i64 = 3 // edge-orientation layout L1 (crop/recompose tolerant)
34const NX_IT_KIND_LOCAL: i64 = 4 // RESERVED: local keypoints + geometric verification
35const NX_IT_KIND_SEMANTIC: i64 = 5 // RESERVED: quantised learned embedding
45const NX_IT_CLASS_IDENTITY: i64 = 1
46const NX_IT_CLASS_SIMILAR: i64 = 2
51const NX_IT_COPY_THRESH: i64 = 10 // live nx_image_search default; ruler det@10 confirms it
52const NX_IT_COPY_MAX: i64 = 64 // dHash is 64 bits
57const NX_IT_LOCAL_MAX: i64 = 24 // == KP_MAX
63const NX_IT_LOCAL_MININLIERS: i64 = 5
72const NX_IT_LOCAL_SWEPT_MININLIERS: i64 = 7
73const NX_IT_LOCAL_THRESH: i64 = 19 // KP_MAX - NX_IT_LOCAL_MININLIERS
74const NX_IT_SIMILAR_MAX: i64 = 20480 // 80 dims x 256 max per-dim spread
81const NX_IT_SIMILAR_THRESH: i64 = 1767
94const NX_IT_MIN_BITS: i64 = 6
97const NX_IT_MIN_CELLS: i64 = 4
116const NX_IMGTIER_BYTES: i64 = 96

functions

119func nx_imgtier_kind(t: *nx_imgtier) -> i64 { return t.kind }
called by 1: ie_tier_is_hash
120func nx_imgtier_klass(t: *nx_imgtier) -> i64 { return t.klass }
121func nx_imgtier_name(t: *nx_imgtier) -> *u8 { return t.name_ptr as *u8 }
122func nx_imgtier_idx_dim(t: *nx_imgtier) -> i64 { return t.idx_dim }
123func nx_imgtier_qry_dim(t: *nx_imgtier) -> i64 { return t.qry_dim }
124func nx_imgtier_threshold(t: *nx_imgtier) -> i64 { return t.threshold }
125func nx_imgtier_max_dist(t: *nx_imgtier) -> i64 { return t.max_dist }
126func nx_imgtier_weight(t: *nx_imgtier) -> i64 { return t.weight }
136func nx_imgtier_describe_index(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
140func nx_imgtier_describe_query(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
144func nx_imgtier_distance(t: *nx_imgtier, q: *i64, d: *i64) -> i64
148func nx_imgtier_informative(t: *nx_imgtier, d: *i64) -> i64
155func nx_imgtier_score(t: *nx_imgtier, dist: i64) -> i64
167func it_copy_describe(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
calls 1: nx_phash_dhash
171func it_copy_distance(t: *nx_imgtier, q: *i64, d: *i64) -> i64
177func it_hash_informative(t: *nx_imgtier, d: *i64) -> i64
184func nx_imgtier_copy_init(t: *nx_imgtier, threshold: i64, weight: i64) -> i64
called by 1: nx_imgtier_new
204func it_orient_describe_index(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
calls 1: nx_phash_dhash
208func it_orient_describe_query(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
211func it_orient_distance(t: *nx_imgtier, q: *i64, d: *i64) -> i64
215func nx_imgtier_orient_init(t: *nx_imgtier, threshold: i64, weight: i64) -> i64
called by 1: nx_imgtier_new
235func it_similar_describe(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
238func it_similar_distance(t: *nx_imgtier, q: *i64, d: *i64) -> i64
calls 1: nx_visdesc_l1
243func it_similar_informative(t: *nx_imgtier, d: *i64) -> i64
254func nx_imgtier_similar_init(t: *nx_imgtier, threshold: i64, weight: i64) -> i64
called by 1: nx_imgtier_new
276func it_local_describe(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
281func it_local_describe_query(t: *nx_imgtier, gray: *u8, rgb: *u8, w: i64, h: i64, out: *i64) -> i64
284func it_local_distance_one(q: *i64, d: *i64) -> i64
314func it_local_distance(t: *nx_imgtier, q: *i64, d: *i64) -> i64
339func it_local_informative(t: *nx_imgtier, d: *i64) -> i64
calls 1: nx_imgkp_count
344func nx_imgtier_local_init(t: *nx_imgtier, threshold: i64, weight: i64) -> i64
361func nx_imgtier_new(kind: i64, threshold: i64, weight: i64) -> *nx_imgtier