nx_imgquery.nx source
↩ module page · 51 lines · 2314 B
1// nx_imgquery.nx -- HYBRID reverse-image query: two complementary tiers over one corpus.
2// COPY tier -- dHash Hamming <= copy_thresh: exact/near DUPLICATES (TinEye-style, what dHash is for).
3// SIMILAR tier -- imgsig (visdesc structure + colordesc color) L1 nearest: VISUALLY-ALIKE images that
4// are NOT byte-copies (Google-style). dHash is colorblind and structure-blind to scale,
5// so the similar tier surfaces matches the copy tier structurally cannot.
6// Caller holds parallel arrays: dhashes[i] (i64), sigs[i] (i64 = pointer to that item's 112-dim imgsig),
7// pays[i] (payload/docid). Linear scan here (correct + simple); nx_phash_index (BK-tree) is the scale tier.
8// Composes nx_imgsig + nx_phash -- ZERO new ranking math. license_tier: ORIGINAL
9import "nx_imgsig.nx"
10import "nx_phash.nx"
11
12// COPY tier: payloads whose dHash is within copy_thresh Hamming of the query. returns count;
13// out[i]=payload, out_ham[i]=Hamming.
14func nx_imgquery_copies(q_dhash: i64, dhashes: *i64, pays: *i64, n: i64, copy_thresh: i64, out: *i64, out_ham: *i64) -> i64 {
15 var m: i64 = 0
16 var i: i64 = 0
17 while i < n {
18 let hh: i64 = nx_simhash_hamming(q_dhash, dhashes[i])
19 if hh <= copy_thresh { out[m] = pays[i]; out_ham[m] = hh; m = m + 1 }
20 i = i + 1
21 }
22 return m
23}
24
25// SIMILAR tier: the topk corpus items by ascending imgsig L1 to the query (repeated-min, n small).
26// out[i]=payload, out_l1[i]=imgsig L1. `taken` is caller scratch of length >= n.
27func nx_imgquery_similar(q_sig: *i64, sigs: *i64, pays: *i64, n: i64, topk: i64, out: *i64, out_l1: *i64, taken: *i64) -> i64 {
28 var i: i64 = 0
29 while i < n { taken[i] = 0; i = i + 1 }
30 var m: i64 = 0
31 while m < topk {
32 if m >= n { return m }
33 var best: i64 = 0 - 1
34 var bestl: i64 = 0
35 var j: i64 = 0
36 while j < n {
37 if taken[j] == 0 {
38 let sj: *i64 = sigs[j] as *i64
39 let l1: i64 = nx_imgsig_l1(q_sig, sj)
40 if best < 0 { best = j; bestl = l1 } else { if l1 < bestl { best = j; bestl = l1 } }
41 }
42 j = j + 1
43 }
44 if best < 0 { return m }
45 taken[best] = 1
46 out[m] = pays[best]
47 out_l1[m] = bestl
48 m = m + 1
49 }
50 return m
51}