nx_lbp_faceindex.nx source
↩ module page · 108 lines · 4927 B
1// nx_lbp_faceindex.nx -- SOVEREIGN face-descriptor RUNG 6: cluster the corpus descriptor store into people.
2// Reads knowledge/status/galx_face_descr.bin (fixed records {cid(72) + 16384 i64}), packs the descriptors,
3// runs cluster_greedy (nx_lbp_core) at a chi-square threshold (arg1, scale=1000), and writes:
4// galx_face_index.tsv = cid \t cluster_id (consumed by the gallery &person= filter)
5// galx_persons.tsv = cluster_id \t count \t rep_cid (sorted by count DESC -> the People dropdown)
6// Prints M / cluster count / top cluster sizes so the threshold can be tuned by MEASUREMENT.
7// Build/run: ./_offc/nx_sov_build_run.elf nx_lbp_faceindex [thresh] license_tier: ORIGINAL
8import "nx_syscalls.nx"
9import "nx_lbp_core.nx"
10const K_MAGIC_8000000: i64 = 8000000
11
12const REC: i64 = 131144 // 72 (cid, null-padded, 8-aligned) + 16384*8 (descriptor)
13const D: i64 = 16384 // 8x8 grid * 256 bins
14
15func fi_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8) { if s[i]>=(48 as u8) { if s[i]<=(57 as u8) { v=v*10+((s[i] as i64)-48) } } i=i+1 } return v }
16// write decimal v at buf+off; returns number of bytes written
17func fi_num(buf: *u8, off: i64, v: i64) -> i64 {
18 var m: i64=v; if m<0 { m=0-m }
19 let tmp: *u8 = sys_mmap(28); var k: i64=0
20 if m==0 { tmp[0]=48; k=1 }
21 while m>0 { tmp[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
22 var w: i64=0
23 if v<0 { buf[off]=45 as u8; w=1 }
24 var z: i64=0; while z<k { buf[off+w+z]=tmp[k-1-z]; z=z+1 }
25 return w+k
26}
27func fi_sift(idx: *i64, key: *i64, root0: i64, n: i64) -> i64 {
28 var root: i64=root0; var go: i64=1
29 while go==1 { let c: i64=2*root+1; if c>=n { go=0 } else { var s: i64=root; if key[idx[s]]<key[idx[c]] { s=c } if c+1<n { if key[idx[s]]<key[idx[c+1]] { s=c+1 } } if s==root { go=0 } else { let t: i64=idx[root]; idx[root]=idx[s]; idx[s]=t; root=s } } }
30 return 0
31}
32func fi_heapsort(idx: *i64, key: *i64, n: i64) -> i64 {
33 if n<2 { return 0 }
34 var st: i64=n/2-1; while st>=0 { fi_sift(idx,key,st,n); st=st-1 }
35 var e: i64=n-1; while e>0 { let t: i64=idx[0]; idx[0]=idx[e]; idx[e]=t; fi_sift(idx,key,0,e); e=e-1 }
36 return 0
37}
38
39func main(argc: i64, argv: *i64) -> i64 {
40 var thresh: i64 = K_MAGIC_8000000
41 if argc >= 2 { thresh = fi_atoi(argv[1] as *u8) }
42
43 let szp: *i64 = sys_mmap(16) as *i64
44 let store: *u8 = sys_read_file("knowledge/status/galx_face_descr.bin" as *u8, szp)
45 let fsz: i64 = szp[0]
46 if (store as i64)==0 { lp("FACEINDEX FAIL: no descr store\n" as *u8); sys_exit(1); return 1 }
47 let M: i64 = fsz / REC
48 if M==0 { lp("FACEINDEX FAIL: empty store\n" as *u8); sys_exit(1); return 1 }
49
50 // pack descriptors into a contiguous d-stride array for cluster_greedy
51 let descrs: *i64 = sys_mmap(8*M*D) as *i64
52 var r: i64=0
53 while r<M {
54 let dsrc: *i64 = ((store as i64) + r*REC + 72) as *i64
55 var k: i64=0; while k<D { descrs[r*D+k]=dsrc[k]; k=k+1 }
56 r=r+1
57 }
58
59 let assign: *i64 = sys_mmap(8*M) as *i64
60 let reps: *i64 = sys_mmap(8*M) as *i64
61 let nc: i64 = cluster_greedy(descrs, M, D, thresh, 1000, assign, reps)
62 lp("M=" as *u8); ln(M); lp(" thresh=" as *u8); ln(thresh); lp(" clusters=" as *u8); ln(nc); lp("\n" as *u8)
63
64 let cnt: *i64 = sys_mmap(8*nc) as *i64
65 var ci: i64=0; while ci<nc { cnt[ci]=0; ci=ci+1 }
66 var a: i64=0; while a<M { cnt[assign[a]]=cnt[assign[a]]+1; a=a+1 }
67
68 // galx_face_index.tsv : cid \t cluster
69 let fd1: i64 = sys_openat_wr("knowledge/status/galx_face_index.tsv" as *u8, 0x1a4)
70 let line: *u8 = sys_mmap(256)
71 var ii: i64=0
72 while ii<M {
73 var lo: i64=0; let cb: i64=ii*REC
74 var k: i64=0; while k<69 { line[lo]=store[cb+k]; lo=lo+1; k=k+1 }
75 line[lo]=9 as u8; lo=lo+1
76 lo = lo + fi_num(line, lo, assign[ii])
77 line[lo]=10 as u8; lo=lo+1
78 sys_write(fd1, line, lo)
79 ii=ii+1
80 }
81 sys_close(fd1)
82
83 // galx_persons.tsv : cluster \t count \t rep_cid (count DESC)
84 let idx: *i64 = sys_mmap(8*nc) as *i64
85 var j: i64=0; while j<nc { idx[j]=j; j=j+1 }
86 fi_heapsort(idx, cnt, nc)
87 let fd2: i64 = sys_openat_wr("knowledge/status/galx_persons.tsv" as *u8, 0x1a4)
88 var rr: i64=nc-1
89 while rr>=0 {
90 let cl: i64=idx[rr]
91 var lo: i64=0
92 lo = lo + fi_num(line, lo, cl)
93 line[lo]=9 as u8; lo=lo+1
94 lo = lo + fi_num(line, lo, cnt[cl])
95 line[lo]=9 as u8; lo=lo+1
96 let cb: i64=reps[cl]*REC; var k: i64=0; while k<69 { line[lo]=store[cb+k]; lo=lo+1; k=k+1 }
97 line[lo]=10 as u8; lo=lo+1
98 sys_write(fd2, line, lo)
99 rr=rr-1
100 }
101 sys_close(fd2)
102
103 lp("top cluster sizes: " as *u8)
104 var t: i64=nc-1; var shown: i64=0
105 while t>=0 { if shown<10 { ln(cnt[idx[t]]); lp(" " as *u8); shown=shown+1 } t=t-1 }
106 lp("\nnx_lbp_faceindex RUNG6 done -> galx_face_index.tsv + galx_persons.tsv\n" as *u8)
107 sys_exit(0); return 0
108}