code wiki / _hdl_build / nx_poseest2.nx

nx_poseest2.nx source

↩ module page · 167 lines · 7514 B

1// nx_poseest2.nx -- R2 v0 with the pose-estimate funcs INLINED (importing nx_pose_estimate TOGETHER WITH 2// nx_figure_render tripped an nx_cc empty-.s codegen bug; each alone compiles -> module-combination bug, routed 3// to the compiler workstream). Learned hand-region-from-silhouette, held-out generalization. expect_exit:0 ORIGINAL 4import "nx_syscalls.nx" 5import "nx_figure_render.nx" 6const K_MAGIC_1900000000: i64 = 1900000000 7const K_MAGIC_12868: i64 = 12868 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 } 11 12const PW: i64 = 64 13const PH: i64 = 48 14const GW: i64 = 8 15const GH: i64 = 6 16const NCELL: i64 = 48 17const NFEAT: i64 = 49 18const NR: i64 = 3 // hand HEIGHT bands (low/mid/high) -- the signal shoulder pitch most strongly drives 19const NTR: i64 = 30 20const NHO: i64 = 9 21const NALL: i64 = 39 22 23// ---- inlined pose-estimate ---- 24func pe_occ(zb: *i64, w: i64, h: i64, gw: i64, gh: i64, occ: *i64) -> i64 { 25 var cy: i64 = 0 26 while cy < gh { 27 var cx: i64 = 0 28 while cx < gw { 29 let x0: i64 = cx*w/gw; let x1: i64 = (cx+1)*w/gw; let y0: i64 = cy*h/gh; let y1: i64 = (cy+1)*h/gh 30 var cnt: i64 = 0; var tot: i64 = 0 31 var y: i64 = y0 32 while y < y1 { var x: i64 = x0; while x < x1 { tot=tot+1; if zb[y*w+x] > (0-K_MAGIC_1900000000) { cnt=cnt+1 } x=x+1 } y=y+1 } 33 var v: i64 = 0 34 if tot > 0 { v = cnt*256/tot } 35 occ[cy*gw+cx] = v 36 cx = cx + 1 37 } 38 cy = cy + 1 39 } 40 return 0 41} 42func pe_score(W: *i64, r: i64, occ: *i64, nf: i64) -> i64 { var s: i64=0; var c: i64=0; while c<nf { s=s+W[r*nf+c]*occ[c]; c=c+1 } return s } 43func pe_predict(W: *i64, occ: *i64, nf: i64, nr: i64) -> i64 { var best: i64=0; var bs: i64=pe_score(W,0,occ,nf); var r: i64=1; while r<nr { let s: i64=pe_score(W,r,occ,nf); if s>bs { bs=s; best=r } r=r+1 } return best } 44func pe_train(W: *i64, occs: *i64, labels: *i64, ns: i64, nf: i64, nr: i64, ep: i64) -> i64 { 45 var i: i64=0; while i<nr*nf { W[i]=0; i=i+1 } 46 var last: i64=0; var e: i64=0 47 while e < ep { 48 var mist: i64=0; var n: i64=0 49 while n < ns { 50 let occ: *i64 = (occs as i64 + n*nf*8) as *i64 51 let pred: i64 = pe_predict(W, occ, nf, nr); let lab: i64 = labels[n] 52 if pred != lab { mist=mist+1; var c: i64=0; while c<nf { W[lab*nf+c]=W[lab*nf+c]+occ[c]; W[pred*nf+c]=W[pred*nf+c]-occ[c]; c=c+1 } } 53 n = n + 1 54 } 55 last = mist; e = e + 1 56 } 57 return last 58} 59func clamp3(v: i64) -> i64 { if v < 0 { return 0 } if v > 2 { return 2 } return v } 60func pdg(d: i64) -> i64 { return d * K_MAGIC_12868 / 180 } // degrees -> rig angle unit (md_deg lives in nx_movelib, not imported here) 61func pe_sample(sk: i64, fb: *i64, zb: *i64, pitch: i64, elbow: i64, occ: *i64, wxy: *i64) -> i64 { 62 sk_pose(sk, RG_SHR, 0, pdg(pitch)); sk_pose(sk, RG_ELR, pdg(elbow), 0) 63 sk_update(sk) 64 rig_draw(sk, fb, zb, PW, PH, pdg(15), 70) 65 pe_occ(zb, PW, PH, GW, GH, occ) 66 occ[NCELL] = 256 67 let bw: *i64 = sk_bone(sk, RG_WRR); wxy[0] = bw[15]; wxy[1] = bw[16] 68 return 0 69} 70 71func main() -> i64 { 72 hw("=== nx_poseest2 -- learned hand-region from silhouette (R2 v0) ===\n" as *u8) 73 let sk: i64 = sys_mmap(sk_bytes()) as i64 74 let fb: *i64 = sys_mmap(PW * PH * 8) as *i64 75 let zb: *i64 = sys_mmap(PW * PH * 8) as *i64 76 let occs: *i64 = sys_mmap(NALL * NFEAT * 8) as *i64 77 let wx: *i64 = sys_mmap(NALL * 8) as *i64 78 let wy: *i64 = sys_mmap(NALL * 8) as *i64 79 let trp: *i64 = sys_mmap(6 * 8) as *i64 80 trp[0]=0-70; trp[1]=0-40; trp[2]=0-10; trp[3]=20; trp[4]=50; trp[5]=80 81 let tre: *i64 = sys_mmap(5 * 8) as *i64 82 tre[0]=0; tre[1]=25; tre[2]=50; tre[3]=75; tre[4]=100 83 let hop: *i64 = sys_mmap(3 * 8) as *i64 84 hop[0]=0-55; hop[1]=5; hop[2]=65 85 let hoe: *i64 = sys_mmap(3 * 8) as *i64 86 hoe[0]=12; hoe[1]=37; hoe[2]=62 87 88 rig_build(sk) 89 let wxy: *i64 = sys_mmap(2 * 8) as *i64 90 // DELTA FEATURES: a neutral arm-down reference silhouette; every sample subtracts it, so the STATIC body 91 // cancels and the moving ARM is the signal the perceptron sees. 92 let ref: *i64 = sys_mmap(NFEAT * 8) as *i64 93 pe_sample(sk, fb, zb, 0 - 80, 0, ref, wxy) 94 var idx: i64 = 0 95 var pi: i64 = 0 96 while pi < 6 { 97 var ei: i64 = 0 98 while ei < 5 { 99 let occp: *i64 = (occs as i64 + idx * NFEAT * 8) as *i64 100 pe_sample(sk, fb, zb, trp[pi], tre[ei], occp, wxy) 101 var c: i64 = 0 102 while c < NCELL { occp[c] = occp[c] - ref[c]; c = c + 1 } 103 wx[idx] = wxy[0]; wy[idx] = wxy[1]; idx = idx + 1 104 ei = ei + 1 105 } 106 pi = pi + 1 107 } 108 pi = 0 109 while pi < 3 { 110 var ei: i64 = 0 111 while ei < 3 { 112 let occp: *i64 = (occs as i64 + idx * NFEAT * 8) as *i64 113 pe_sample(sk, fb, zb, hop[pi], hoe[ei], occp, wxy) 114 var c: i64 = 0 115 while c < NCELL { occp[c] = occp[c] - ref[c]; c = c + 1 } 116 wx[idx] = wxy[0]; wy[idx] = wxy[1]; idx = idx + 1 117 ei = ei + 1 118 } 119 pi = pi + 1 120 } 121 122 var xmin: i64 = wx[0]; var xmax: i64 = wx[0]; var ymin: i64 = wy[0]; var ymax: i64 = wy[0] 123 var i: i64 = 1 124 while i < NALL { 125 if wx[i] < xmin { xmin = wx[i] } 126 if wx[i] > xmax { xmax = wx[i] } 127 if wy[i] < ymin { ymin = wy[i] } 128 if wy[i] > ymax { ymax = wy[i] } 129 i = i + 1 130 } 131 let labels: *i64 = sys_mmap(NALL * 8) as *i64 132 i = 0 133 while i < NALL { 134 let yr: i64 = clamp3(3 * (wy[i] - ymin) / (ymax - ymin + 1)) 135 labels[i] = yr // 3 height bands 136 i = i + 1 137 } 138 hw(" wrist range x["); pn(xmin); hw(","); pn(xmax); hw("] y["); pn(ymin); hw(","); pn(ymax); hw("]\n" as *u8) 139 140 let W: *i64 = sys_mmap(NR * NFEAT * 8) as *i64 141 let mist: i64 = pe_train(W, occs, labels, NTR, NFEAT, NR, 60) 142 hw(" perceptron trained on "); pn(NTR); hw(" poses, last-epoch mistakes="); pn(mist); hw("\n" as *u8) 143 144 let W0: *i64 = sys_mmap(NR * NFEAT * 8) as *i64 145 var z: i64 = 0 146 while z < NR * NFEAT { W0[z] = 0; z = z + 1 } 147 var corr: i64 = 0 148 var corr0: i64 = 0 149 i = NTR 150 while i < NALL { 151 let occ: *i64 = (occs as i64 + i * NFEAT * 8) as *i64 152 if pe_predict(W, occ, NFEAT, NR) == labels[i] { corr = corr + 1 } 153 if pe_predict(W0, occ, NFEAT, NR) == labels[i] { corr0 = corr0 + 1 } 154 i = i + 1 155 } 156 hw(" HELD-OUT: TRAINED "); pn(corr); hw("/"); pn(NHO); hw(" vs UNTRAINED "); pn(corr0); hw("/"); pn(NHO); hw("\n" as *u8) 157 158 var fails: i64 = 0 159 if corr > corr0 { 160 if corr * 100 >= NHO * 55 { hw("T PASS GENERALIZES (trained "); pn(corr); hw("/"); pn(NHO); hw(" >> untrained "); pn(corr0); hw(")\n" as *u8) } 161 else { fails = fails + 1; hw("T FAIL accuracy low "); pn(corr); hw("\n" as *u8) } 162 } else { fails = fails + 1; hw("T FAIL not > untrained\n" as *u8) } 163 164 if fails == 0 { hw("POSEEST2 GREEN -- learned pose localization generalizes (R2 v0; coarse, our-render domain)\n" as *u8); sys_exit(0); return 0 } 165 hw("POSEEST2 RED fails="); pn(fails); hw("\n" as *u8) 166 sys_exit(1); return 1 167}