code wiki / (root) / nx_ocr_classify_gate.nx

nx_ocr_classify_gate.nx source

↩ module page · 67 lines · 3369 B

1// nx_ocr_classify_gate.nx -- proves R4 (glyph -> character). Templates for '0','1','7' on a 3x5 grid. Renders a '7' 2// as a binary image, resamples it, and classifies it correctly; checks Hamming distance and 1-pixel noise tolerance. 3// Exit 0 iff all pass. license_tier: ORIGINAL 4import "nx_gate.nx" 5import "nx_ocr_classify.nx" 6import "nx_img_core.nx" 7 8func chk(name: *u8, got: i64, want: i64, st: *i64) -> i64 { 9 if got == want { st[0] = st[0] + 1; gw(" PASS " as *u8); gw(name); gw("\n" as *u8) } 10 else { st[1] = st[1] + 1; gw(" FAIL " as *u8); gw(name); gw(" got=" as *u8); gn(got); gw(" want=" as *u8); gn(want); gw("\n" as *u8) } 11 return 0 12} 13 14func set15(t: *i64, o: i64, a0: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64, a7: i64, a8: i64, a9: i64, a10: i64, a11: i64, a12: i64, a13: i64, a14: i64) -> i64 { 15 t[o+0]=a0; t[o+1]=a1; t[o+2]=a2; t[o+3]=a3; t[o+4]=a4; t[o+5]=a5; t[o+6]=a6; t[o+7]=a7 16 t[o+8]=a8; t[o+9]=a9; t[o+10]=a10; t[o+11]=a11; t[o+12]=a12; t[o+13]=a13; t[o+14]=a14 17 return 0 18} 19 20func main() -> i64 { 21 let st: *i64 = sys_mmap(16) as *i64 22 st[0] = 0; st[1] = 0 23 let NC: i64 = 15 // 3x5 24 25 // template set: index 0='0', 1='1', 2='7' 26 let tpl: *i64 = sys_mmap(3 * 15 * 8) as *i64 27 set15(tpl, 0, 1,1,1, 1,0,1, 1,0,1, 1,0,1, 1,1,1) // '0' 28 set15(tpl, 15, 0,1,0, 1,1,0, 0,1,0, 0,1,0, 1,1,1) // '1' 29 set15(tpl, 30, 1,1,1, 0,0,1, 0,1,0, 0,1,0, 0,1,0) // '7' 30 31 // render a '7' as a 3x5 binary image (ink=0, paper=255) 32 let src: *u8 = "P2\n3 5\n255\n0 0 0\n255 255 0\n255 0 255\n255 0 255\n255 0 255\n" as *u8 33 var len: i64 = 0; while src[len] != (0 as u8) { len = len + 1 } 34 let pix: *u8 = sys_mmap(256) 35 let dims: *i64 = sys_mmap(64) as *i64 36 let n: i64 = img_pgm_decode(src, len, pix, 256, dims) 37 chk("decoded 15-pixel glyph" as *u8, n, 15, st) 38 39 // resample the whole 3x5 glyph (bbox 0,0,3,5) into a 3x5 grid 40 let cell: *i64 = sys_mmap(15 * 8) as *i64 41 ocr_resample(pix, 3, 0, 0, 3, 5, 3, 5, cell) 42 let t7: *i64 = ((tpl as i64) + 30 * 8) as *i64 43 chk("resampled '7' matches template exactly (Hamming 0)" as *u8, ocr_hamming(cell, t7, NC), 0, st) 44 45 // classify -> should be index 2 ('7'), distance 0 46 let bd: *i64 = sys_mmap(16) as *i64 47 chk("classify '7' -> template index 2" as *u8, ocr_classify(cell, NC, tpl, 3, bd), 2, st) 48 chk("classify '7' distance = 0" as *u8, bd[0], 0, st) 49 50 // distance between distinct templates '0' and '7' 51 let t0: *i64 = ((tpl as i64) + 0 * 8) as *i64 52 chk("Hamming('0','7') = 9" as *u8, ocr_hamming(t0, t7, NC), 9, st) 53 54 // copy the '0' template into a cell and classify -> index 0 55 var i: i64 = 0; while i < NC { cell[i] = t0[i]; i = i + 1 } 56 chk("classify clean '0' -> index 0" as *u8, ocr_classify(cell, NC, tpl, 3, bd), 0, st) 57 58 // flip ONE cell (noise) -> still classified '0', distance 1 59 cell[4] = 1 - cell[4] 60 chk("classify noisy '0' (1 flip) -> still index 0" as *u8, ocr_classify(cell, NC, tpl, 3, bd), 0, st) 61 chk("noisy '0' distance = 1" as *u8, bd[0], 1, st) 62 63 gw("nx_ocr_classify_gate: PASS=" as *u8); gn(st[0]); gw(" FAIL=" as *u8); gn(st[1]); gw("\n" as *u8) 64 if st[1] == 0 { gw("R4 nx_ocr_classify: GREEN (glyph -> char: resample + nearest-neighbour template match)\n" as *u8); return 0 } 65 gw("R4 nx_ocr_classify: RED\n" as *u8) 66 return 1 67}