code wiki / (root) / nx_revimg_discover.nx

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}