nx_areola_texture.nx source
↩ module page · 95 lines · 3675 B
1// nx_areola_texture.nx -- areola micro-texture realism (NEAR-fidelity proxy).
2// Center-of-torso GLCM as approximation; concept_fidelity_q10 = 512.
3
4// nx_safety_envelope:
5// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
6// sil_target: SIL1
7// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
8// verdict: NOT_YET_EVALUATED
9
10import "nx_syscalls.nx"
11import "nx_image.nx"
12import "nx_texture.nx"
13import "nx_region.nx"
14import "nx_skin_texture.nx"
15const NX_MAGIC_1024: i64 = 1024
16
17const NX_AT_UNKNOWN: i64 = 0
18const NX_AT_REALISTIC: i64 = 1
19const NX_AT_TOO_SMOOTH: i64 = 2
20
21const NX_AT_ENERGY_SMOOTH_Q10: i64 = 900
22const NX_AT_CONTRAST_SMOOTH_Q10: i64 = 50
23const NX_AT_CENTER_X_MIN_Q10: i64 = 307
24const NX_AT_CENTER_X_MAX_Q10: i64 = 717
25const NX_AT_CENTER_Y_MIN_Q10: i64 = 410
26const NX_AT_CENTER_Y_MAX_Q10: i64 = 717
27
28struct AreolaTextureVerdict {
29 kind: i64,
30 torso_present: i64,
31 center_glcm_contrast_q10: i64,
32 center_glcm_energy_q10: i64,
33 center_glcm_homogeneity_q10: i64,
34 center_pixels: i64,
35 severity_q10: i64,
36 fidelity_q10: i64,
37}
38
39func nx_areola_texture_compute(rgb: *Image, verdict: *AreolaTextureVerdict) -> i64 {
40 verdict.kind = NX_AT_UNKNOWN
41 verdict.torso_present = 0
42 verdict.center_glcm_contrast_q10 = 0
43 verdict.center_glcm_energy_q10 = 0
44 verdict.center_glcm_homogeneity_q10 = 0
45 verdict.center_pixels = 0
46 verdict.severity_q10 = 0
47 verdict.fidelity_q10 = 0
48
49 let set: *RegionSet = nx_region_segment(rgb)
50 let t_idx: i64 = nx_region_find_kind(set, NX_REGION_TORSO)
51 if t_idx < 0 { return 0 }
52 verdict.torso_present = 1
53
54 let t_min_x: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MIN_X)
55 let t_min_y: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MIN_Y)
56 let t_max_x: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MAX_X)
57 let t_max_y: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MAX_Y)
58 let t_w: i64 = t_max_x - t_min_x + 1
59 let t_h: i64 = t_max_y - t_min_y + 1
60
61 let cx0: i64 = t_min_x + (t_w * NX_AT_CENTER_X_MIN_Q10) / NX_MAGIC_1024
62 let cy0: i64 = t_min_y + (t_h * NX_AT_CENTER_Y_MIN_Q10) / NX_MAGIC_1024
63 let cx1: i64 = t_min_x + (t_w * NX_AT_CENTER_X_MAX_Q10) / NX_MAGIC_1024
64 let cy1: i64 = t_min_y + (t_h * NX_AT_CENTER_Y_MAX_Q10) / NX_MAGIC_1024
65 let cw: i64 = cx1 - cx0
66 let ch: i64 = cy1 - cy0
67 if cw <= 1 { return 0 }
68 if ch <= 1 { return 0 }
69 verdict.center_pixels = cw * ch
70
71 let gray: *Image = nx_image_to_grayscale(rgb)
72 let center_gray: *Image = nx_skin_crop_gray(gray, cx0, cy0, cx1, cy1)
73 let glcm: *i64 = (sys_mmap(64 * 8 + 16)) as *i64
74 nx_texture_glcm(center_gray, 1, 0, glcm)
75 let contrast: i64 = nx_texture_contrast(glcm)
76 let energy: i64 = nx_texture_energy(glcm)
77 let homogeneity: i64 = nx_texture_homogeneity(glcm)
78 verdict.center_glcm_contrast_q10 = contrast
79 verdict.center_glcm_energy_q10 = energy
80 verdict.center_glcm_homogeneity_q10 = homogeneity
81
82 if energy >= NX_AT_ENERGY_SMOOTH_Q10 {
83 if contrast < NX_AT_CONTRAST_SMOOTH_Q10 {
84 verdict.kind = NX_AT_TOO_SMOOTH
85 verdict.severity_q10 = 640
86 }
87 }
88 if verdict.kind == NX_AT_UNKNOWN {
89 verdict.kind = NX_AT_REALISTIC
90 verdict.severity_q10 = 0
91 }
92 let t_conf: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_CONF_Q10)
93 verdict.fidelity_q10 = t_conf / 2
94 return 0
95}