code wiki / (root) / nx_critic_axes.nx

nx_critic_axes.nx source

↩ module page · 114 lines · 4319 B

1// nx_critic_axes.nx -- the SHARED measured-quality AXES (extracted so every loop/gate scores emitted output 2// with the SAME rulers as the critic -- one formula, many callers; nx_critic_visual/nx_photoreal_critic are 3// the calibration/epistemics home, this is the reusable measurement lib; consolidation: point them here later). 4// Axes: fine_detail (1px micro-contrast over foreground) · structure (8x8 block-mean variance -- a real object 5// has low-freq form, noise/flat do not) · chroma MAD. Overall = MIN axis (hard chain). license_tier: ORIGINAL 6import "nx_syscalls.nx" 7 8func ca_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 9func ca_clamp(v: i64) -> i64 { if v < 0 { return 0 } if v > 1000 { return 1000 } return v } 10func ca_lum(g: i64) -> i64 { return ((g & 255) + ((g >> 8) & 255) + ((g >> 16) & 255)) / 3 } 11func ca_fg(g: i64) -> i64 { let r: i64 = g & 255; let b: i64 = (g >> 16) & 255; if r >= b { return 1 } return 0 } 12func ca_chromaof(g: i64) -> i64 { 13 let r: i64 = g & 255 14 let gg: i64 = (g >> 8) & 255 15 let b: i64 = (g >> 16) & 255 16 var mx: i64 = r 17 if gg > mx { mx = gg } 18 if b > mx { mx = b } 19 var mn: i64 = r 20 if gg < mn { mn = gg } 21 if b < mn { mn = b } 22 return mx - mn 23} 24// foreground pixel count (is there content at all) 25func ca_fgcount(fb: *i64, w: i64, h: i64) -> i64 { 26 var n: i64 = 0 27 var i: i64 = 0 28 while i < w * h { if ca_fg(fb[i]) == 1 { n = n + 1 } i = i + 1 } 29 return n 30} 31// fine micro-contrast over foreground (raw; skin-pore target ~32) 32func ca_fine_detail(fb: *i64, w: i64, h: i64) -> i64 { 33 var fg: i64 = 0 34 var s: i64 = 0 35 var y: i64 = 1 36 while y < h - 1 { 37 var x: i64 = 1 38 while x < w - 1 { 39 let c: i64 = fb[y * w + x] 40 if ca_fg(c) == 1 { 41 let nb: i64 = (ca_lum(fb[y * w + x - 1]) + ca_lum(fb[y * w + x + 1]) + ca_lum(fb[(y - 1) * w + x]) + ca_lum(fb[(y + 1) * w + x])) / 4 42 s = s + ca_abs(ca_lum(c) - nb) 43 fg = fg + 1 44 } 45 x = x + 1 46 } 47 y = y + 1 48 } 49 if fg < 1 { fg = 1 } 50 return s / fg 51} 52// low-frequency STRUCTURE: variance of the 8x8 block-mean luminance grid (raw; object ~tens, noise/flat ~0) 53func ca_structure(fb: *i64, w: i64, h: i64) -> i64 { 54 let G: i64 = 8 55 let means: *i64 = sys_mmap(G * G * 8) as *i64 56 var gy: i64 = 0 57 while gy < G { 58 var gx: i64 = 0 59 while gx < G { 60 let x0: i64 = gx * w / G 61 let x1: i64 = (gx + 1) * w / G 62 let y0: i64 = gy * h / G 63 let y1: i64 = (gy + 1) * h / G 64 var sum: i64 = 0 65 var cnt: i64 = 0 66 var y: i64 = y0 67 while y < y1 { 68 var x: i64 = x0 69 while x < x1 { sum = sum + ca_lum(fb[y * w + x]); cnt = cnt + 1; x = x + 1 } 70 y = y + 1 71 } 72 if cnt < 1 { cnt = 1 } 73 means[gy * G + gx] = sum / cnt 74 gx = gx + 1 75 } 76 gy = gy + 1 77 } 78 var mean: i64 = 0 79 var i: i64 = 0 80 while i < G * G { mean = mean + means[i]; i = i + 1 } 81 mean = mean / (G * G) 82 var v: i64 = 0 83 i = 0 84 while i < G * G { let d: i64 = means[i] - mean; v = v + d * d; i = i + 1 } 85 return v / (G * G) 86} 87// chroma MAD over foreground (raw; skin variation target ~16) 88func ca_chroma_mad(fb: *i64, w: i64, h: i64) -> i64 { 89 var fg: i64 = 0 90 var s: i64 = 0 91 var i: i64 = 0 92 while i < w * h { if ca_fg(fb[i]) == 1 { s = s + ca_chromaof(fb[i]); fg = fg + 1 } i = i + 1 } 93 if fg < 1 { fg = 1 } 94 let cm: i64 = s / fg 95 var mad: i64 = 0 96 i = 0 97 while i < w * h { if ca_fg(fb[i]) == 1 { mad = mad + ca_abs(ca_chromaof(fb[i]) - cm) } i = i + 1 } 98 return mad / fg 99} 100// overall = MIN of the scaled axes (same hard-chain rule + scales as the critic) 101func ca_score(fb: *i64, w: i64, h: i64) -> i64 { 102 let d: i64 = ca_clamp(ca_fine_detail(fb, w, h) * 1000 / 32) 103 let st: i64 = ca_clamp(ca_structure(fb, w, h) * 1000 / 45) 104 let ch: i64 = ca_clamp(ca_chroma_mad(fb, w, h) * 1000 / 16) 105 var mn: i64 = d 106 if st < mn { mn = st } 107 if ch < mn { mn = ch } 108 return mn 109} 110func ca_verdict(s: i64) -> *u8 { 111 if s >= 700 { return "PHOTOREAL" as *u8 } 112 if s >= 400 { return "STYLIZED-CG" as *u8 } 113 return "CLAY" as *u8 114}