nx_revimg_discover.nx source
↩ module page · 82 lines · 4090 B
1// nx_revimg_discover.nx -- REVERSE-IMAGE CROSS-SITE DISCOVERY engine: the "grow the search results" loop.
2// Given an entity's media fingerprints (the SEED set -- e.g. the Diora Baird images nx_media_gather pulls
3// in) and a crawled corpus of (site, image-fingerprint) records, it answers the operator's three asks:
4// 1. WHICH OTHER SITES host this media? -- perceptual match (dHash Hamming <= thresh), so it catches
5// RECOMPRESSED/rescaled reposts, not just byte-identical copies (sha256 can't).
6// 2. WHAT OTHER MEDIA do those host sites have? -- harvest a host's non-seed images = the entity's other
7// media we didn't have yet.
8// 3. GROW -- fold the harvest back into the seed set and re-discover: new media surfaces new host sites.
9// Fingerprints come from nx_phash (dHash) over decoded images; matching reuses nx_simhash_hamming
10// (popcount64 of XOR) -- ZERO new ranking math. Linear scan here; nx_phash_index (BK-tree) is the scale
11// tier. HONEST: harvesting a host's non-seed images is co-location-based (a fan/official page of the
12// entity is mostly entity media); the grow loop's cross-site re-match is what verifies a harvested image
13// is really the entity (it must reappear on another host). license_tier: ORIGINAL
14import "nx_simhash.nx"
15
16// MATCH: every (seed, corpus-image) pair within `thresh` Hamming -> "this site hosts this seed's media".
17// records (corpus_index, seed_index, ham) into the parallel out arrays; returns match count.
18func nx_revimg_match(seeds: *i64, nseed: i64, corpus_fp: *i64, ncorp: i64, thresh: i64,
19 out_ci: *i64, out_si: *i64, out_ham: *i64, out_cap: i64) -> i64 {
20 var m: i64 = 0
21 var s: i64 = 0
22 while s < nseed {
23 var c: i64 = 0
24 while c < ncorp {
25 let hh: i64 = nx_simhash_hamming(seeds[s], corpus_fp[c])
26 if hh <= thresh { if m < out_cap { out_ci[m]=c; out_si[m]=s; out_ham[m]=hh; m=m+1 } }
27 c = c + 1
28 }
29 s = s + 1
30 }
31 return m
32}
33
34// HOST SITES: distinct sites hosting >=1 seed, with hits = how many DISTINCT seed media each hosts.
35// A site that carries more of the entity's media is more relevant (caller can sort by out_hits).
36// returns the number of host sites.
37func nx_revimg_host_sites(seeds: *i64, nseed: i64, corpus_fp: *i64, corpus_site: *i64, ncorp: i64, thresh: i64,
38 out_site: *i64, out_hits: *i64, out_cap: i64) -> i64 {
39 var nsites: i64 = 0
40 var c0: i64 = 0
41 while c0 < ncorp {
42 let sid: i64 = corpus_site[c0]
43 var seen: i64 = 0
44 var k: i64 = 0
45 while k < nsites { if out_site[k]==sid { seen=1 } k=k+1 }
46 if seen==0 {
47 var hits: i64 = 0
48 var s: i64 = 0
49 while s < nseed {
50 var matched: i64 = 0
51 var c: i64 = 0
52 while c < ncorp {
53 if corpus_site[c]==sid { if matched==0 { if nx_simhash_hamming(seeds[s], corpus_fp[c])<=thresh { matched=1 } } }
54 c = c + 1
55 }
56 hits = hits + matched
57 s = s + 1
58 }
59 if hits > 0 { if nsites < out_cap { out_site[nsites]=sid; out_hits[nsites]=hits; nsites=nsites+1 } }
60 }
61 c0 = c0 + 1
62 }
63 return nsites
64}
65
66// HARVEST a host site's OTHER media: its corpus images that are NOT within thresh of ANY current seed
67// (so they are NEW = candidate entity media we did not already have). fills out_fp[]/out_ci[]; returns count.
68func nx_revimg_harvest(site: i64, seeds: *i64, nseed: i64, corpus_fp: *i64, corpus_site: *i64, ncorp: i64, thresh: i64,
69 out_fp: *i64, out_ci: *i64, out_cap: i64) -> i64 {
70 var m: i64 = 0
71 var c: i64 = 0
72 while c < ncorp {
73 if corpus_site[c]==site {
74 var isnew: i64 = 1
75 var s: i64 = 0
76 while s < nseed { if nx_simhash_hamming(seeds[s], corpus_fp[c])<=thresh { isnew=0 } s=s+1 }
77 if isnew==1 { if m<out_cap { out_fp[m]=corpus_fp[c]; out_ci[m]=c; m=m+1 } }
78 }
79 c = c + 1
80 }
81 return m
82}