nx_cheek_localize.nx source
↩ module page · 62 lines · 2504 B
1// nx_cheek_localize.nx -- derive cheek bbox from face bbox via Loomis canon.
2//
3// The Loomis face canon places cheekbones at ~50-65% down the face,
4// ~15-35% in from each side. The substrate uses this heuristic to
5// produce a cheek region for nx_response_signal's flushed-cheek check
6// without needing facial-landmark detection.
7//
8// Output flat-array (left_cheek + right_cheek bboxes packed):
9// result[0..3] left cheek: x0, y0, x1, y1
10// result[4..7] right cheek: x0, y0, x1, y1
11
12// nx_safety_envelope:
13// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
14// sil_target: SIL1
15// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
16// verdict: NOT_YET_EVALUATED
17
18import "nx_syscalls.nx"
19
20// Canonical Y-band (% down face) for cheekbone region.
21const NX_CHEEK_Y_FRAC_TOP_PCT: i64 = 50
22const NX_CHEEK_Y_FRAC_BOT_PCT: i64 = 65
23// Canonical X-band (% from each side) for each cheek.
24const NX_CHEEK_X_FRAC_INNER_PCT: i64 = 15
25const NX_CHEEK_X_FRAC_OUTER_PCT: i64 = 35
26
27const NX_CHEEK_RES_LEFT_X0: i64 = 0
28const NX_CHEEK_RES_LEFT_Y0: i64 = 1
29const NX_CHEEK_RES_LEFT_X1: i64 = 2
30const NX_CHEEK_RES_LEFT_Y1: i64 = 3
31const NX_CHEEK_RES_RIGHT_X0: i64 = 4
32const NX_CHEEK_RES_RIGHT_Y0: i64 = 5
33const NX_CHEEK_RES_RIGHT_X1: i64 = 6
34const NX_CHEEK_RES_RIGHT_Y1: i64 = 7
35const NX_CHEEK_RES_FIELDS: i64 = 8
36
37func nx_cheek_localize(face_x0: i64, face_y0: i64,
38 face_x1: i64, face_y1: i64,
39 result: *i64) -> i64 {
40 let face_w: i64 = face_x1 - face_x0
41 let face_h: i64 = face_y1 - face_y0
42 if face_w <= 0 { return 1 }
43 if face_h <= 0 { return 2 }
44
45 let y_top: i64 = face_y0 + (face_h * NX_CHEEK_Y_FRAC_TOP_PCT) / 100
46 let y_bot: i64 = face_y0 + (face_h * NX_CHEEK_Y_FRAC_BOT_PCT) / 100
47 let inner_inset: i64 = (face_w * NX_CHEEK_X_FRAC_INNER_PCT) / 100
48 let outer_inset: i64 = (face_w * NX_CHEEK_X_FRAC_OUTER_PCT) / 100
49
50 // Left cheek: from face_x0 + inner_inset to face_x0 + outer_inset.
51 result[NX_CHEEK_RES_LEFT_X0] = face_x0 + inner_inset
52 result[NX_CHEEK_RES_LEFT_Y0] = y_top
53 result[NX_CHEEK_RES_LEFT_X1] = face_x0 + outer_inset
54 result[NX_CHEEK_RES_LEFT_Y1] = y_bot
55
56 // Right cheek: mirrored from face_x1.
57 result[NX_CHEEK_RES_RIGHT_X0] = face_x1 - outer_inset
58 result[NX_CHEEK_RES_RIGHT_Y0] = y_top
59 result[NX_CHEEK_RES_RIGHT_X1] = face_x1 - inner_inset
60 result[NX_CHEEK_RES_RIGHT_Y1] = y_bot
61 return 0
62}