code wiki / (root) / nx_pose_cnn.nx

nx_pose_cnn.nx source

↩ module page · 52 lines · 3388 B

1// nx_pose_cnn.nx -- T2 POSE FRONT-HALF: the sovereign software-f32 pose-CNN FORWARD PASS -- the heatmap PRODUCER 2// that was the one remaining gap sitting UNDER nx_pose_keypoints. It composes the gated f32 vision substrate 3// (nx_f32_conv2d_forward, itself only nx_f32_mul/nx_f32_add) into the real heatmap-pose-net SHAPE: 4// a 3x3 stride-1 pad-1 spatial-conv BACKBONE stage (the ResBlock-class feature extractor) 5// + a 1x1 conv HEAD that projects the feature channels into J per-joint confidence heatmaps, 6// each followed by a ReLU that makes every heatmap value NON-NEGATIVE. 7// 8// KEY INVARIANT (load-bearing, why this closes the loop with NO glue): IEEE-754 non-negative floats are 9// ORDER-ISOMORPHIC to their i64 bit-patterns -- for x,y >= +0.0, (x > y) as floats iff (bits(x) > bits(y)) as 10// integers. So a ReLU'd heatmap can be consumed DIRECTLY by the integer, weights-free back-half nx_pose_keypoints 11// (argmax + quarter-pixel subpixel + occlusion threshold) with NO f32->int conversion. The ReLU is REQUIRED: a 12// negative activation carries the sign bit, whose pattern sorts ABOVE any positive peak, so the integer argmax 13// would pick the wrong cell -- ReLU zeroing negatives to +0.0 is exactly what restores the isomorphism. 14// 15// This closes the pipeline image -> f32 conv backbone -> f32 1x1 head -> heatmaps -> integer keypoint back-half, 16// end-to-end and sovereignly, on hand-set weights. Only TRAINED WEIGHTS + a deeper backbone remain (the T3 arc); 17// the architecture + the arithmetic are proven here. NO libm, NO Q-scaling -- only nx_f32_conv2d/mul/add/gt. 18// license_tier: ORIGINAL 19import "nx_syscalls.nx" 20import "nx_f32.nx" 21import "nx_f32_conv2d.nx" 22 23// ReLU in place over n f32 values: negative / -0.0 / NaN -> +0.0 (bits 0). This is what makes the heatmap block 24// bit-order-isomorphic to the integers, so the downstream integer argmax in nx_pose_keypoints is correct. Without 25// it a negative activation's bit-pattern (sign bit set) sorts ABOVE a positive peak and argmax picks the wrong cell. 26func pose_cnn_relu(buf: *i64, n: i64) -> i64 { 27 var i: i64 = 0 28 while i < n { 29 if nx_f32_gt(buf[i], 0) == 0 { buf[i] = 0 } // v > +0.0 ? keep : clamp to +0.0 30 i = i + 1 31 } 32 return 0 33} 34 35// 3x3 stride-1 pad-1 spatial-conv BACKBONE stage (ResBlock-class feature extractor), C_in -> C_out, then ReLU. 36// inp is [1,C_in,H,W]; weight is f32 [C_out,C_in,3,3]; bias is f32 [C_out] or 0; out is [C_out,H,W] (H,W preserved). 37func pose_cnn_backbone3x3(inp: *i64, C_in: i64, H: i64, W: i64, weight: *i64, C_out: i64, bias: *i64, out: *i64) -> i64 { 38 let rc: i64 = nx_f32_conv2d_forward(inp, 1, C_in, H, W, weight, C_out, 3, 3, 1, 1, bias, out) 39 if rc != 0 { return rc } 40 pose_cnn_relu(out, C_out * H * W) 41 return 0 42} 43 44// 1x1 conv HEAD: project C_in feature channels -> J joint heatmaps (the actual last layer of a heatmap pose net), 45// then ReLU so the J*H*W block is non-negative and consumable by nx_pose_keypoints/pose_extract with no conversion. 46// feat is [1,C_in,H,W]; weight is f32 [J,C_in,1,1]; bias is f32 [J] or 0; out is [J,H,W]. 47func pose_cnn_head1x1(feat: *i64, C_in: i64, H: i64, W: i64, weight: *i64, J: i64, bias: *i64, out: *i64) -> i64 { 48 let rc: i64 = nx_f32_conv2d_forward(feat, 1, C_in, H, W, weight, J, 1, 1, 1, 0, bias, out) 49 if rc != 0 { return rc } 50 pose_cnn_relu(out, J * H * W) 51 return 0 52}