code wiki / (root) / nx_outfit_coverage.nx

nx_outfit_coverage.nx source

↩ module page · 107 lines · 3915 B

1// nx_outfit_coverage.nx -- outfit-coverage detector. 2// 3// Non-skin density inside expanded torso bbox -> NUDE/MINIMAL/PARTIAL/DRESSED. 4 5// nx_safety_envelope: 6// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 7// sil_target: SIL1 8// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 9// verdict: NOT_YET_EVALUATED 10 11import "nx_syscalls.nx" 12import "nx_image.nx" 13import "nx_color_v2.nx" 14import "nx_region.nx" 15const NX_MAGIC_1024: i64 = 1024 16 17const NX_OC_UNKNOWN: i64 = 0 18const NX_OC_NUDE: i64 = 1 19const NX_OC_MINIMAL: i64 = 2 20const NX_OC_PARTIAL: i64 = 3 21const NX_OC_DRESSED: i64 = 4 22 23const NX_OC_NUDE_MAX_Q10: i64 = 154 24const NX_OC_MINIMAL_MAX_Q10: i64 = 358 25const NX_OC_PARTIAL_MAX_Q10: i64 = 614 26const NX_OC_EXPAND_PCT: i64 = 30 27 28struct OutfitCoverageVerdict { 29 kind: i64, 30 torso_present: i64, 31 bbox_area: i64, 32 expanded_bbox_area: i64, 33 skin_pixels: i64, 34 non_skin_pixels: i64, 35 coverage_q10: i64, 36 severity_q10: i64, 37 fidelity_q10: i64, 38} 39 40func nx_outfit_coverage_compute(rgb: *Image, verdict: *OutfitCoverageVerdict) -> i64 { 41 verdict.kind = NX_OC_UNKNOWN 42 verdict.torso_present = 0 43 verdict.bbox_area = 0 44 verdict.expanded_bbox_area = 0 45 verdict.skin_pixels = 0 46 verdict.non_skin_pixels = 0 47 verdict.coverage_q10 = 0 48 verdict.severity_q10 = 0 49 verdict.fidelity_q10 = 0 50 51 let set: *RegionSet = nx_region_segment(rgb) 52 let t_idx: i64 = nx_region_find_kind(set, NX_REGION_TORSO) 53 if t_idx < 0 { return 0 } 54 verdict.torso_present = 1 55 56 let w: i64 = rgb.width 57 let h: i64 = rgb.height 58 let t_min_x: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MIN_X) 59 let t_min_y: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MIN_Y) 60 let t_max_x: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MAX_X) 61 let t_max_y: i64 = nx_region_get_field(set, t_idx, NX_REGION_F_BBOX_MAX_Y) 62 let t_w: i64 = t_max_x - t_min_x + 1 63 let t_h: i64 = t_max_y - t_min_y + 1 64 verdict.bbox_area = t_w * t_h 65 66 let exp_x: i64 = (t_w * NX_OC_EXPAND_PCT) / 100 67 let exp_y: i64 = (t_h * NX_OC_EXPAND_PCT) / 100 68 var ex_min_x: i64 = t_min_x - exp_x 69 var ex_min_y: i64 = t_min_y - exp_y 70 var ex_max_x: i64 = t_max_x + exp_x 71 var ex_max_y: i64 = t_max_y + exp_y 72 if ex_min_x < 0 { ex_min_x = 0 } 73 if ex_min_y < 0 { ex_min_y = 0 } 74 if ex_max_x >= w { ex_max_x = w - 1 } 75 if ex_max_y >= h { ex_max_y = h - 1 } 76 verdict.expanded_bbox_area = (ex_max_x - ex_min_x + 1) * (ex_max_y - ex_min_y + 1) 77 78 let mask: *Image = nx_color_skin_mask(rgb) 79 var skin_count: i64 = 0 80 var nonskin_count: i64 = 0 81 var y: i64 = ex_min_y 82 while y <= ex_max_y { 83 var x: i64 = ex_min_x 84 while x <= ex_max_x { 85 if nx_image_get(mask, x, y, 0) > 0 { skin_count = skin_count + 1 } 86 if nx_image_get(mask, x, y, 0) == 0 { nonskin_count = nonskin_count + 1 } 87 x = x + 1 88 } 89 y = y + 1 90 } 91 verdict.skin_pixels = skin_count 92 verdict.non_skin_pixels = nonskin_count 93 let total: i64 = skin_count + nonskin_count 94 if total > 0 { verdict.coverage_q10 = (nonskin_count * NX_MAGIC_1024) / total } 95 96 let cov: i64 = verdict.coverage_q10 97 if cov < NX_OC_NUDE_MAX_Q10 { verdict.kind = NX_OC_NUDE } 98 if cov >= NX_OC_NUDE_MAX_Q10 { 99 if cov < NX_OC_MINIMAL_MAX_Q10 { verdict.kind = NX_OC_MINIMAL } 100 if cov >= NX_OC_MINIMAL_MAX_Q10 { 101 if cov < NX_OC_PARTIAL_MAX_Q10 { verdict.kind = NX_OC_PARTIAL } 102 if cov >= NX_OC_PARTIAL_MAX_Q10 { verdict.kind = NX_OC_DRESSED } 103 } 104 } 105 verdict.fidelity_q10 = nx_region_get_field(set, t_idx, NX_REGION_F_CONF_Q10) 106 return 0 107}