nx_ocr_classify.nx source
↩ module page · 48 lines · 2115 B
1// nx_ocr_classify.nx -- R4 of the sovereign scanning stack: glyph box -> character. The recognition core: resample
2// a segmented glyph (its bbox in the binary image) to a fixed GW x GH grid, then classify by NEAREST-NEIGHBOUR
3// (minimum Hamming distance) against a template set. This is classical template-match OCR for MACHINE PRINT --
4// integer-exact, zero deps, no ML. Coverage/accuracy grows with the template set (later rungs); this rung proves the
5// mechanism. R5 assembles recognised chars into text -> nx_money_ledger -> money-OS. license_tier: ORIGINAL
6import "nx_syscalls.nx"
7
8// resample the glyph in pix (0=ink) within bbox [minx,miny]+bw x bh into a gw x gh binary grid (cell=1 if ink).
9// nearest-cell sampling (an R0 method; area-averaging is a later refinement).
10func ocr_resample(pix: *u8, w: i64, minx: i64, miny: i64, bw: i64, bh: i64, gw: i64, gh: i64, cell: *i64) -> i64 {
11 var oy: i64 = 0
12 while oy < gh {
13 var ox: i64 = 0
14 while ox < gw {
15 let sx: i64 = minx + ox * bw / gw
16 let sy: i64 = miny + oy * bh / gh
17 var v: i64 = 0
18 if pix[sy * w + sx] == (0 as u8) { v = 1 }
19 cell[oy * gw + ox] = v
20 ox = ox + 1
21 }
22 oy = oy + 1
23 }
24 return 0
25}
26
27// Hamming distance between two binary grids of ncells.
28func ocr_hamming(a: *i64, b: *i64, ncells: i64) -> i64 {
29 var d: i64 = 0; var i: i64 = 0
30 while i < ncells { if a[i] != b[i] { d = d + 1 } i = i + 1 }
31 return d
32}
33
34// nearest-neighbour classify: return the template index with min Hamming distance; best distance via best_out[0].
35// templates is a flat i64 array of ntempl blocks, each ncells cells.
36func ocr_classify(cell: *i64, ncells: i64, templates: *i64, ntempl: i64, best_out: *i64) -> i64 {
37 var best: i64 = 0 - 1
38 var bestd: i64 = ncells + 1
39 var t: i64 = 0
40 while t < ntempl {
41 let tp: *i64 = ((templates as i64) + t * ncells * 8) as *i64
42 let d: i64 = ocr_hamming(cell, tp, ncells)
43 if d < bestd { bestd = d; best = t }
44 t = t + 1
45 }
46 best_out[0] = bestd
47 return best
48}