code wiki / (root) / nx_colordesc_gate.nx

nx_colordesc_gate.nx source

↩ module page · 205 lines · 9889 B

1// nx_colordesc_gate.nx -- referee for the chroma color-layout descriptor (nx_colordesc). 2// PROVES the color axis grayscale throws away. Corpus = 4 color classes (red/green/blue/yellow), 3// 4 instances each varying additive brightness + per-channel noise. 4// row1 RETRIEVAL: precision@3 by COLOR class (each image has 3 same-color peers). 5// row2 BEYOND-GRAYSCALE (headline exceed): a luma-MATCHED red field and green field have identical 6// grayscale (dHash Hamming == 0 -> the gray engine cannot tell them apart) yet a LARGE colordesc 7// L1 -> color sees what dHash/visdesc structurally cannot. 8// row3 BRIGHTNESS INVARIANCE: +uniform brightness leaves chroma unchanged (L1 ~ 0, by construction). 9// row4 DETERMINISM: same image twice -> identical descriptor (L1 == 0). 10// row5 SEPARATION: cross-color avg L1 >> same-color avg L1 (no collapse). 11// GREEN iff 5/5. Durable verdict -> knowledge/status/colordesc_gate.log. license_tier: ORIGINAL 12import "nx_colordesc.nx" 13import "nx_phash.nx" 14 15func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 16func g_num(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=(48 as u8);k=1}; while m>0{t[k]=((48+(m%10)) as u8);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(1,bb,k); return 0 } 17func g_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 18func g_wn(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=(48 as u8);k=1}; while m>0{t[k]=((48+(m%10)) as u8);m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 19 20func g_clamp255(v: i64) -> i64 { if v<0 { return 0 } if v>255 { return 255 } return v } 21 22// flat color fill (no noise) -- for the clean luma-matched headline pair. 23func g_fill_rgb(buf: *u8, w: i64, h: i64, r: i64, g: i64, b: i64) -> i64 { 24 var i: i64 = 0 25 let n: i64 = w*h 26 while i < n { buf[i*3]=g_clamp255(r) as u8; buf[i*3+1]=g_clamp255(g) as u8; buf[i*3+2]=g_clamp255(b) as u8; i=i+1 } 27 return 0 28} 29// color field with additive brightness + deterministic per-channel noise (instances differ). 30func g_synth_rgb(buf: *u8, w: i64, h: i64, r: i64, g: i64, b: i64, dbright: i64, phase: i64) -> i64 { 31 var y: i64 = 0 32 while y < h { 33 var x: i64 = 0 34 while x < w { 35 let idx: i64 = (y*w+x)*3 36 buf[idx] = g_clamp255(r + dbright + ((x*7 + y*13 + phase*5) & 7)) as u8 37 buf[idx+1] = g_clamp255(g + dbright + ((x*5 + y*11 + phase*3) & 7)) as u8 38 buf[idx+2] = g_clamp255(b + dbright + ((x*3 + y*17 + phase*7) & 7)) as u8 39 x = x + 1 40 } 41 y = y + 1 42 } 43 return 0 44} 45// interleaved RGB -> row-major luma (Rec.601 integer), so we can dHash the grayscale view. 46func g_rgb_to_gray(rgb: *u8, gray: *u8, w: i64, h: i64) -> i64 { 47 var i: i64 = 0 48 let n: i64 = w*h 49 while i < n { 50 let r: i64 = rgb[i*3] as i64 51 let g: i64 = rgb[i*3+1] as i64 52 let b: i64 = rgb[i*3+2] as i64 53 gray[i] = g_clamp255((77*r + 150*g + 29*b) / 256) as u8 54 i = i + 1 55 } 56 return 0 57} 58 59func main() -> i64 { 60 g_puts("=== COLORDESC GATE (color-layout: distinguishes hue grayscale collapses) ===\n" as *u8) 61 let W: i64 = 32 62 let H: i64 = 32 63 let NPX: i64 = W*H 64 let NINST: i64 = 4 65 let NIMG: i64 = 16 66 67 // 4 color classes 68 let CR: *i64 = sys_mmap(8*4) as *i64 69 let CG: *i64 = sys_mmap(8*4) as *i64 70 let CB: *i64 = sys_mmap(8*4) as *i64 71 CR[0]=210; CG[0]=30; CB[0]=30 // red 72 CR[1]=30; CG[1]=170; CB[1]=40 // green 73 CR[2]=40; CG[2]=40; CB[2]=210 // blue 74 CR[3]=200; CG[3]=190; CB[3]=40 // yellow 75 76 let descs: *i64 = sys_mmap(8*NIMG) as *i64 77 var k: i64 = 0 78 while k < NIMG { 79 let cls: i64 = k / NINST 80 let inst: i64 = k % NINST 81 let buf: *u8 = sys_mmap(NPX*3) 82 g_synth_rgb(buf, W, H, CR[cls], CG[cls], CB[cls], inst*10, inst) 83 let d: *i64 = sys_mmap(8*32) as *i64 84 nx_colordesc_extract(buf, W, H, d) 85 descs[k] = d as i64 86 k = k + 1 87 } 88 89 var pass: i64 = 0 90 let rows: i64 = 5 91 92 // ---- row1: retrieval precision@3 by color ---- 93 let taken: *i64 = sys_mmap(8*NIMG) as *i64 94 let TOPK: i64 = 3 95 var pk_num: i64 = 0 96 var nn_same: i64 = 0 97 k = 0 98 while k < NIMG { 99 let dk: *i64 = descs[k] as *i64 100 var t: i64 = 0 101 while t < NIMG { taken[t] = 0; t = t + 1 } 102 taken[k] = 1 103 var rank: i64 = 0 104 while rank < TOPK { 105 var best: i64 = 0-1 106 var bestd: i64 = 0 107 var j: i64 = 0 108 while j < NIMG { 109 if taken[j] == 0 { 110 let dj: *i64 = descs[j] as *i64 111 let l1: i64 = nx_colordesc_l1(dk, dj) 112 if best < 0 { best = j; bestd = l1 } else { if l1 < bestd { best = j; bestd = l1 } } 113 } 114 j = j + 1 115 } 116 if best >= 0 { 117 taken[best] = 1 118 if (best/NINST) == (k/NINST) { pk_num = pk_num + 1 } 119 if rank == 0 { if (best/NINST) == (k/NINST) { nn_same = nn_same + 1 } } 120 } 121 rank = rank + 1 122 } 123 k = k + 1 124 } 125 var pk_permil: i64 = 0 126 if NIMG*TOPK > 0 { pk_permil = pk_num * 1000 / (NIMG*TOPK) } 127 g_puts(" row1 retrieval P@3=" as *u8); g_num(pk_permil); g_puts("permil (1-NN same-color=" as *u8); g_num(nn_same); g_puts("/" as *u8); g_num(NIMG); g_puts(") -> " as *u8) 128 if pk_permil >= 750 { pass=pass+1; g_puts("PASS (color retrieval)\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 129 130 // ---- row2: luma-matched red vs green -- gray collapses (dHash ham 0), color separates ---- 131 let rgbR: *u8 = sys_mmap(NPX*3) 132 g_fill_rgb(rgbR, W, H, 204, 0, 0) // luma ~61 133 let rgbG: *u8 = sys_mmap(NPX*3) 134 g_fill_rgb(rgbG, W, H, 0, 105, 0) // luma ~61 135 let gR: *u8 = sys_mmap(NPX) 136 let gG: *u8 = sys_mmap(NPX) 137 g_rgb_to_gray(rgbR, gR, W, H) 138 g_rgb_to_gray(rgbG, gG, W, H) 139 let lumaR: i64 = gR[0] as i64 140 let lumaG: i64 = gG[0] as i64 141 let dhR: i64 = nx_phash_dhash(gR, W, H) 142 let dhG: i64 = nx_phash_dhash(gG, W, H) 143 let gray_ham: i64 = nx_simhash_hamming(dhR, dhG) 144 let cdR: *i64 = sys_mmap(8*32) as *i64 145 let cdG: *i64 = sys_mmap(8*32) as *i64 146 nx_colordesc_extract(rgbR, W, H, cdR) 147 nx_colordesc_extract(rgbG, W, H, cdG) 148 let color_l1: i64 = nx_colordesc_l1(cdR, cdG) 149 g_puts(" row2 red(luma=" as *u8); g_num(lumaR); g_puts(") vs green(luma=" as *u8); g_num(lumaG); g_puts("): grayscale dHash ham=" as *u8); g_num(gray_ham) 150 g_puts(" (identical), colordesc L1=" as *u8); g_num(color_l1); g_puts(" (distinct) -> " as *u8) 151 if gray_ham <= 2 { if color_l1 > 200 { pass=pass+1; g_puts("PASS (color sees what gray cannot)\n" as *u8) } else { g_puts("FAIL\n" as *u8) } } else { g_puts("FAIL\n" as *u8) } 152 153 // ---- row3: brightness invariance (uniform +40 to all channels) ---- 154 let rgbRB: *u8 = sys_mmap(NPX*3) 155 g_fill_rgb(rgbRB, W, H, 244, 40, 40) // red + 40 on every channel 156 let cdRB: *i64 = sys_mmap(8*32) as *i64 157 nx_colordesc_extract(rgbRB, W, H, cdRB) 158 let bri_l1: i64 = nx_colordesc_l1(cdR, cdRB) 159 g_puts(" row3 brightness invariance -> L1(red, red+40)=" as *u8); g_num(bri_l1); g_puts(" (small) -> " as *u8) 160 if bri_l1 < 40 { pass=pass+1; g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 161 162 // ---- row4: determinism ---- 163 let cdR2: *i64 = sys_mmap(8*32) as *i64 164 nx_colordesc_extract(rgbR, W, H, cdR2) 165 let det_l1: i64 = nx_colordesc_l1(cdR, cdR2) 166 g_puts(" row4 determinism -> L1(extract,extract)=" as *u8); g_num(det_l1); g_puts(" (==0) -> " as *u8) 167 if det_l1 == 0 { pass=pass+1; g_puts("PASS\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 168 169 // ---- row5: separation (cross-color L1 >> same-color L1) ---- 170 var ssum: i64 = 0 171 var scnt: i64 = 0 172 var xsum: i64 = 0 173 var xcnt: i64 = 0 174 var a: i64 = 0 175 while a < NIMG { 176 var b: i64 = a+1 177 while b < NIMG { 178 let da: *i64 = descs[a] as *i64 179 let db: *i64 = descs[b] as *i64 180 let l1: i64 = nx_colordesc_l1(da, db) 181 if (a/NINST) == (b/NINST) { ssum = ssum + l1; scnt = scnt + 1 } else { xsum = xsum + l1; xcnt = xcnt + 1 } 182 b = b + 1 183 } 184 a = a + 1 185 } 186 var savg: i64 = 0 187 if scnt > 0 { savg = ssum / scnt } 188 var xavg: i64 = 0 189 if xcnt > 0 { xavg = xsum / xcnt } 190 g_puts(" row5 separation -> same-color avg L1=" as *u8); g_num(savg); g_puts(" cross-color avg L1=" as *u8); g_num(xavg); g_puts(" (~" as *u8) 191 if savg>0 { g_num(xavg/savg) } else { g_num(0) } 192 g_puts("x) -> " as *u8) 193 if xavg > 2*savg { pass=pass+1; g_puts("PASS (clear color separation)\n" as *u8) } else { g_puts("FAIL\n" as *u8) } 194 195 g_puts("----\nCOLORDESC-GATE rows=" as *u8); g_num(rows); g_puts(" pass=" as *u8); g_num(pass); g_puts("\n" as *u8) 196 let lg: i64 = sys_openat_append("knowledge/status/colordesc_gate.log" as *u8, 0x1a4) 197 if lg>=0 { 198 g_w(lg,"COLORDESC-GATE rows=" as *u8); g_wn(lg,rows); g_w(lg," pass=" as *u8); g_wn(lg,pass) 199 g_w(lg," p_at_3=" as *u8); g_wn(lg,pk_permil); g_w(lg," gray_ham=" as *u8); g_wn(lg,gray_ham); g_w(lg," color_l1=" as *u8); g_wn(lg,color_l1); g_w(lg," sameL1=" as *u8); g_wn(lg,savg); g_w(lg," crossL1=" as *u8); g_wn(lg,xavg) 200 if pass==rows { g_w(lg," verdict=GREEN\n" as *u8) } else { g_w(lg," verdict=RED\n" as *u8) } 201 sys_close(lg) 202 } 203 if pass==rows { g_puts("COLORDESC-GATE GREEN\n" as *u8); sys_exit(0); return 0 } 204 g_puts("COLORDESC-GATE RED\n" as *u8); sys_exit(1); return 1 205}