nx_pose_skeleton.nx source
↩ module page · 52 lines · 2977 B
1// nx_pose_skeleton.nx -- T2 POSE, the geometric skeleton analysis that turns keypoints (from nx_pose_keypoints)
2// into a coarse POSTURE = the first rung of position/dance classification. NO CNN, NO trig, NO float: the body
3// ORIENTATION comes from the spine vector (neck -> mid-hip) by comparing the dominant axis + its sign (image
4// coords: y DOWN). Composes with nx_pose_keypoints' quarter-pixel keypoints; ready for real skeletons once the
5// f32 pose CNN emits heatmaps. Honest first rung -- trained fine-grained position recognition is T3.
6// license_tier: ORIGINAL
7import "nx_syscalls.nx"
8
9// midpoint of two joints (virtual joint, e.g. mid-hip from L/R hip) iff both are confident. Returns 1 on valid.
10func pose_mid(qx: *i64, qy: *i64, conf: *i64, a: i64, b: i64, thresh: i64, ox: *i64, oy: *i64) -> i64 {
11 if conf[a] < thresh { return 0 }
12 if conf[b] < thresh { return 0 }
13 ox[0] = (qx[a] + qx[b]) / 2; oy[0] = (qy[a] + qy[b]) / 2
14 return 1
15}
16// coarse body posture from the spine vector (neck -> mid-hip): 0=upright 1=horizontal/lying 2=inverted -1=unknown.
17func pose_posture(qx: *i64, qy: *i64, conf: *i64, thresh: i64, neck_i: i64, lhip_i: i64, rhip_i: i64) -> i64 {
18 if conf[neck_i] < thresh { return 0 - 1 }
19 let hxb: *i64 = sys_mmap(8) as *i64; let hyb: *i64 = sys_mmap(8) as *i64
20 if pose_mid(qx, qy, conf, lhip_i, rhip_i, thresh, hxb, hyb) == 0 { return 0 - 1 }
21 let nx: i64 = qx[neck_i]; let ny: i64 = qy[neck_i]
22 let hx: i64 = hxb[0]; let hy: i64 = hyb[0]
23 var dx: i64 = hx - nx; if dx < 0 { dx = 0 - dx }
24 let dyraw: i64 = hy - ny // >0: hip below neck (normal); <0: hip above neck (head-down)
25 var dy: i64 = dyraw; if dy < 0 { dy = 0 - dy }
26 if dx >= 2 * dy { return 1 } // spine mostly HORIZONTAL -> lying/prone
27 if dyraw < 0 { return 2 } // spine vertical but head-DOWN -> inverted
28 return 0 // spine vertical, head up -> upright
29}
30// bounding-box compactness x1000 = (spanY*1000)/(spanX+1) over confident joints: high=extended/tall, low=crouched/wide.
31// A coarse shape feature the position/dance classifier composes with posture. Returns -1 if <2 confident joints.
32func pose_compactness(qx: *i64, qy: *i64, conf: *i64, J: i64, thresh: i64) -> i64 {
33 var minx: i64 = 0; var maxx: i64 = 0; var miny: i64 = 0; var maxy: i64 = 0
34 var seen: i64 = 0
35 var j: i64 = 0
36 while j < J {
37 if conf[j] >= thresh {
38 if seen == 0 { minx = qx[j]; maxx = qx[j]; miny = qy[j]; maxy = qy[j]; seen = 1 }
39 if seen == 1 {
40 if qx[j] < minx { minx = qx[j] }
41 if qx[j] > maxx { maxx = qx[j] }
42 if qy[j] < miny { miny = qy[j] }
43 if qy[j] > maxy { maxy = qy[j] }
44 }
45 }
46 j = j + 1
47 }
48 if seen == 0 { return 0 - 1 }
49 let spanx: i64 = maxx - minx
50 let spany: i64 = maxy - miny
51 return (spany * 1000) / (spanx + 1)
52}