code wiki / _hdl_build / nx_poseelm_gate.nx
nx_poseelm_gate.nx source
↩ module page · 158 lines · 7579 B
1// nx_poseelm_gate.nx -- R2 v1: does a NONLINEAR learner (ELM = fixed random ReLU projection + trained linear
2// output) crack pose-from-silhouette where the linear perceptron failed? Render arm poses -> occupancy ->
3// project -> perceptron on the projected features -> HELD-OUT generalization (9 hand regions). vs untrained at
4// chance. If trained >> untrained on held-out, R2 v1 works (coarse, our-render domain). expect_exit:0 ORIGINAL
5import "nx_syscalls.nx"
6import "nx_figure_render.nx"
7import "nx_pose_elm.nx"
8
9func hw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
10func pn(v: i64) -> i64 { let b: *u8=sys_mmap(32) as *u8; var x: i64=v; var ng: i64=0; if x<0{ng=1;x=0-x} var i: i64=31; if x==0{b[i]=48 as u8;i=i-1} while x>0{b[i]=(48+x%10) as u8;x=x/10;i=i-1} if ng==1{b[i]=45 as u8;i=i-1} sys_write(1,(b as i64+i+1) as *u8,31-i); return 0 }
11func pdg(d: i64) -> i64 { return d * 12868 / 180 }
12func clamp3(v: i64) -> i64 { if v < 0 { return 0 } if v > 2 { return 2 } return v }
13
14const PW: i64 = 64
15const PH: i64 = 48
16const GW: i64 = 8
17const GH: i64 = 6
18const GC: i64 = 16 // contour columns
19const NCELL: i64 = 32 // per column: top-height + thickness (the arm shows in the UPPER CONTOUR)
20const NH: i64 = 64 // random hidden features
21const NR: i64 = 3 // hand HEIGHT bins (low/mid/high) -- well-posed + balanced; the contour top-height encodes it
22const NTR: i64 = 30
23const NHO: i64 = 9
24const NALL: i64 = 39
25
26// UPPER-CONTOUR feature: per column band, the top-point HEIGHT (PH - topmost foreground row) + the column
27// thickness, scaled ~0..256. A raised arm shows as a tall top-height in its columns -- the arm signal the
28// full-body occupancy drowned.
29func pe_contour(zb: *i64, feat: *i64) -> i64 {
30 var cx: i64 = 0
31 while cx < GC {
32 let x0: i64 = cx*PW/GC; let x1: i64 = (cx+1)*PW/GC
33 var top: i64 = PH; var bot: i64 = 0 - 1
34 var x: i64 = x0
35 while x < x1 {
36 var y: i64 = 0
37 while y < PH { if zb[y*PW+x] > (0-1900000000) { if y < top { top = y } if bot < y { bot = y } } y = y + 1 }
38 x = x + 1
39 }
40 var th: i64 = 0; var bh: i64 = 0
41 if bot >= 0 { th = (PH - top) * 5; bh = (bot - top) * 5 }
42 feat[cx*2] = th; feat[cx*2+1] = bh
43 cx = cx + 1
44 }
45 return 0
46}
47func pe_sample(sk: i64, fb: *i64, zb: *i64, pitch: i64, elbow: i64, occ: *i64, wxy: *i64) -> i64 {
48 sk_pose(sk, RG_SHR, 0, pdg(pitch)); sk_pose(sk, RG_ELR, pdg(elbow), 0)
49 sk_update(sk)
50 rig_draw(sk, fb, zb, PW, PH, pdg(15), 70)
51 pe_contour(zb, occ)
52 let bw: *i64 = sk_bone(sk, RG_WRR); wxy[0]=bw[15]; wxy[1]=bw[16]
53 return 0
54}
55
56func main() -> i64 {
57 hw("=== nx_poseelm_gate -- R2 v1: nonlinear (ELM) pose-from-silhouette ===\n" as *u8)
58 let sk: i64 = sys_mmap(sk_bytes()) as i64
59 let fb: *i64 = sys_mmap(PW * PH * 8) as *i64
60 let zb: *i64 = sys_mmap(PW * PH * 8) as *i64
61 let occs: *i64 = sys_mmap(NALL * NCELL * 8) as *i64
62 let wx: *i64 = sys_mmap(NALL * 8) as *i64
63 let wy: *i64 = sys_mmap(NALL * 8) as *i64
64 let trp: *i64 = sys_mmap(6 * 8) as *i64
65 trp[0]=0-70; trp[1]=0-40; trp[2]=0-10; trp[3]=20; trp[4]=50; trp[5]=80
66 let tre: *i64 = sys_mmap(5 * 8) as *i64
67 tre[0]=0; tre[1]=25; tre[2]=50; tre[3]=75; tre[4]=100
68 let hop: *i64 = sys_mmap(3 * 8) as *i64
69 hop[0]=0-55; hop[1]=5; hop[2]=65
70 let hoe: *i64 = sys_mmap(3 * 8) as *i64
71 hoe[0]=12; hoe[1]=37; hoe[2]=62
72 rig_build(sk)
73 let wxy: *i64 = sys_mmap(2 * 8) as *i64
74 var idx: i64 = 0
75 var pi: i64 = 0
76 while pi < 6 {
77 var ei: i64 = 0
78 while ei < 5 {
79 let occp: *i64 = (occs as i64 + idx * NCELL * 8) as *i64
80 pe_sample(sk, fb, zb, trp[pi], tre[ei], occp, wxy)
81 wx[idx]=wxy[0]; wy[idx]=wxy[1]; idx=idx+1
82 ei = ei + 1
83 }
84 pi = pi + 1
85 }
86 pi = 0
87 while pi < 3 {
88 var ei: i64 = 0
89 while ei < 3 {
90 let occp: *i64 = (occs as i64 + idx * NCELL * 8) as *i64
91 pe_sample(sk, fb, zb, hop[pi], hoe[ei], occp, wxy)
92 wx[idx]=wxy[0]; wy[idx]=wxy[1]; idx=idx+1
93 ei = ei + 1
94 }
95 pi = pi + 1
96 }
97 // region labels (3x3 over wrist x,y)
98 var xmin: i64=wx[0]; var xmax: i64=wx[0]; var ymin: i64=wy[0]; var ymax: i64=wy[0]
99 var i: i64 = 1
100 while i < NALL {
101 if wx[i]<xmin{xmin=wx[i]} if wx[i]>xmax{xmax=wx[i]} if wy[i]<ymin{ymin=wy[i]} if wy[i]>ymax{ymax=wy[i]}
102 i = i + 1
103 }
104 let labels: *i64 = sys_mmap(NALL * 8) as *i64
105 i = 0
106 while i < NALL {
107 labels[i] = clamp3(3*(wy[i]-ymin)/(ymax-ymin+1)) // hand-height bin (low/mid/high)
108 i = i + 1
109 }
110 // DIAGNOSTIC: label distribution (degenerate labels would cap any model at the majority baseline)
111 let hist: *i64 = sys_mmap(NR * 8) as *i64
112 var hi: i64 = 0; while hi < NR { hist[hi]=0; hi=hi+1 }
113 i = 0; while i < NALL { hist[labels[i]] = hist[labels[i]] + 1; i = i + 1 }
114 hw(" label histogram (9 regions):"); hi = 0; while hi < NR { hw(" "); pn(hist[hi]); hi = hi + 1 } hw("\n" as *u8)
115 var ho_hist: *i64 = sys_mmap(NR * 8) as *i64
116 hi = 0; while hi < NR { ho_hist[hi]=0; hi=hi+1 }
117 i = NTR; while i < NALL { ho_hist[labels[i]] = ho_hist[labels[i]] + 1; i = i + 1 }
118 hw(" held-out histogram:"); hi = 0; while hi < NR { hw(" "); pn(ho_hist[hi]); hi = hi + 1 } hw("\n" as *u8)
119
120 // ELM project every sample
121 let R: *i64 = sys_mmap(NH * NCELL * 8) as *i64
122 let bb: *i64 = sys_mmap(NH * 8) as *i64
123 elm_init(R, bb, NH, NCELL, 20260706)
124 let hs: *i64 = sys_mmap(NALL * NH * 8) as *i64
125 i = 0
126 while i < NALL {
127 let occp: *i64 = (occs as i64 + i*NCELL*8) as *i64
128 let hp: *i64 = (hs as i64 + i*NH*8) as *i64
129 elm_project(R, bb, occp, NCELL, NH, hp)
130 i = i + 1
131 }
132 // train the linear output on the projected features
133 let W: *i64 = sys_mmap(NR * NH * 8) as *i64
134 let mist: i64 = elm_train(W, hs, labels, NTR, NH, NR, 80)
135 hw(" ELM (NH="); pn(NH); hw(" random features) trained on "); pn(NTR); hw(" poses, mistakes="); pn(mist); hw("\n" as *u8)
136 // held-out: trained vs untrained
137 let W0: *i64 = sys_mmap(NR * NH * 8) as *i64
138 var z: i64 = 0; while z < NR*NH { W0[z]=0; z=z+1 }
139 var corr: i64 = 0; var corr0: i64 = 0
140 i = NTR
141 while i < NALL {
142 let hp: *i64 = (hs as i64 + i*NH*8) as *i64
143 if elm_predict(W, hp, NH, NR) == labels[i] { corr = corr + 1 }
144 if elm_predict(W0, hp, NH, NR) == labels[i] { corr0 = corr0 + 1 }
145 i = i + 1
146 }
147 hw(" HELD-OUT (9 regions): TRAINED "); pn(corr); hw("/"); pn(NHO); hw(" vs UNTRAINED "); pn(corr0); hw("/"); pn(NHO); hw("\n" as *u8)
148
149 var fails: i64 = 0
150 if corr > corr0 {
151 if corr * 100 >= NHO * 55 { hw("R2-ELM PASS -- nonlinear learner GENERALIZES (trained "); pn(corr); hw("/"); pn(NHO); hw(" >> untrained "); pn(corr0); hw("; random features cracked what linear couldn't)\n" as *u8) }
152 else { fails = fails + 1; hw("R2-ELM WEAK -- trained "); pn(corr); hw("/"); pn(NHO); hw(" (beats untrained "); pn(corr0); hw(" but < 55%; honest: coarse)\n" as *u8) }
153 } else { fails = fails + 1; hw("R2-ELM FAIL -- not > untrained ("); pn(corr); hw(" vs "); pn(corr0); hw(")\n" as *u8) }
154
155 if fails == 0 { hw("POSEELM-GATE GREEN -- R2 v1 nonlinear pose-from-silhouette generalizes (ELM; coarse, our-render domain)\n" as *u8); sys_exit(0); return 0 }
156 hw("POSEELM-GATE RED (R2 still hard -- honest; see numbers above)\n" as *u8)
157 sys_exit(1); return 1
158}