code wiki / (root) / nx_doc_scan_gate.nx

nx_doc_scan_gate.nx source

↩ module page · 94 lines · 4689 B

1// nx_doc_scan_gate.nx -- R4 GATE for the doc-intelligence SCAN/CAPTURE leg: proves sovereign template-match 2// OCR on a decoded bitmap. Recognizes all ten digits (clean match distance 0), recognizes a dollar amount, 3// shows the match distance is a real CONFIDENCE signal (a blank cell matches at a large distance), is robust 4// to inter-cell GAP noise, and decodes a real NetPBM P1 image file into a grid it then recognizes. Exits 0 5// iff ALL pass. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_doc_scan.nx" 8 9func 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 } 10func g_putn(v: i64) -> i64 { 11 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 } 12 var m: i64 = v; if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 13 let d: *u8 = sys_mmap(24); var k: i64 = 0 14 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 15 var j: i64 = k - 1 16 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 } 17 return 0 18} 19func chk(name: *u8, got: i64, want: i64, st: *i64) -> i64 { 20 if got == want { st[0] = st[0] + 1; g_puts(" PASS "); g_puts(name); g_puts("\n") } 21 else { st[1] = st[1] + 1; g_puts(" FAIL "); g_puts(name); g_puts(" got="); g_putn(got); g_puts(" want="); g_putn(want); g_puts("\n") } 22 return 0 23} 24func dstreq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while 1 == 1 { if a[i] != b[i] { return 0 } if a[i] == (0 as u8) { return 1 } i = i + 1 } return 1 } 25func zero(grid: *u8, len: i64) -> i64 { var i: i64 = 0; while i < len { grid[i] = 0 as u8; i = i + 1 } return 0 } 26func seti(a: *i64, i: i64, v: i64) -> i64 { a[i] = v; return 0 } 27 28func main() -> i64 { 29 let st: *i64 = sys_mmap(16) as *i64 30 st[0] = 0; st[1] = 0 31 32 // ---- recognize all ten digits "1234567890" (10 cells x 4 wide) ---- 33 let gw: i64 = 40 34 let grid: *u8 = sys_mmap(gw * 5) 35 zero(grid, gw * 5) 36 let seq: *i64 = sys_mmap(8 * 10) as *i64 37 seti(seq,0,1); seti(seq,1,2); seti(seq,2,3); seti(seq,3,4); seti(seq,4,5) 38 seti(seq,5,6); seti(seq,6,7); seti(seq,7,8); seti(seq,8,9); seti(seq,9,0) 39 var i: i64 = 0 40 while i < 10 { sp_stamp(grid, gw, i * 4, seq[i]); i = i + 1 } 41 let out: *u8 = sys_mmap(32) 42 let maxd: *i64 = sys_mmap(16) as *i64 43 sp_recognize_row(grid, gw, 0, 4, 10, out, maxd) 44 g_puts(" [info] recognized=\""); g_puts(out); g_puts("\" maxdist="); g_putn(maxd[0]); g_puts("\n") 45 chk("recognize all ten digits -> 1234567890", dstreq(out, "1234567890\x00" as *u8), 1, st) 46 chk("clean scan match distance = 0", maxd[0], 0, st) 47 48 // ---- recognize a dollar amount "40000" ---- 49 let gw2: i64 = 20 50 let g2: *u8 = sys_mmap(gw2 * 5) 51 zero(g2, gw2 * 5) 52 let amt: *i64 = sys_mmap(8 * 8) as *i64 53 seti(amt,0,4); seti(amt,1,0); seti(amt,2,0); seti(amt,3,0); seti(amt,4,0) 54 i = 0 55 while i < 5 { sp_stamp(g2, gw2, i * 4, amt[i]); i = i + 1 } 56 let out2: *u8 = sys_mmap(16) 57 sp_recognize_row(g2, gw2, 0, 4, 5, out2, maxd) 58 chk("recognize amount -> 40000", dstreq(out2, "40000\x00" as *u8), 1, st) 59 60 // ---- confidence: a BLANK cell matches at a large distance ---- 61 let blank: *u8 = sys_mmap(4 * 5) 62 zero(blank, 4 * 5) 63 let bd: *i64 = sys_mmap(16) as *i64 64 sp_match(blank, 4, 0, 0, bd) 65 g_puts(" [info] blank-cell match distance="); g_putn(bd[0]); g_puts("\n") 66 var blow: i64 = 0 67 if bd[0] >= 6 { blow = 1 } 68 chk("blank cell -> LOW confidence (distance >= 6)", blow, 1, st) 69 70 // ---- robustness: stray pixels in the inter-cell GAPS do not corrupt recognition ---- 71 g2[0 * gw2 + 3] = 1 as u8 // gap after cell 0 72 g2[2 * gw2 + 7] = 1 as u8 // gap after cell 1 73 let out3: *u8 = sys_mmap(16) 74 sp_recognize_row(g2, gw2, 0, 4, 5, out3, maxd) 75 chk("gap-noise robust -> still 40000", dstreq(out3, "40000\x00" as *u8), 1, st) 76 77 // ---- decode a real NetPBM P1 image file (digit 7) then recognize it ---- 78 let pbm: *u8 = "P1\n3 5\n111\n001\n010\n010\n010\n\x00" as *u8 79 var pn: i64 = 0 80 while pbm[pn] != (0 as u8) { pn = pn + 1 } 81 let img: *u8 = sys_mmap(64) 82 let dims: *i64 = sys_mmap(16) as *i64 83 chk("PBM decode ok", sp_pbm_decode(pbm, pn, img, dims, 64), 0, st) 84 chk("PBM width = 3", dims[0], 3, st) 85 chk("PBM height = 5", dims[1], 5, st) 86 let pd: *i64 = sys_mmap(16) as *i64 87 chk("decoded image recognized as digit 7", sp_match(img, 3, 0, 0, pd), 7, st) 88 chk(" decoded-7 match distance = 0", pd[0], 0, st) 89 90 g_puts("nx_doc_scan_gate: PASS="); g_putn(st[0]); g_puts(" FAIL="); g_putn(st[1]); g_puts("\n") 91 if st[1] == 0 { g_puts("DOC-INTEL R4 nx_doc_scan: GREEN\n"); return 0 } 92 g_puts("DOC-INTEL R4 nx_doc_scan: RED\n") 93 return 1 94}