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}