Darayut commited on
Commit
04cb751
·
verified ·
1 Parent(s): ada0c60

Store the recognizers' and layout model's weights in fp16 (half the download)

Browse files

Weights are stored as fp16 and cast to float32 at load; ONNX Runtime folds the casts. CPU text identical on 325/325 lines, layout pages identical. lines/ unchanged. Model card updated for netra-ocr 1.2.0.

README.md CHANGED
@@ -12,7 +12,6 @@ tags:
12
  - khmer-ocr
13
  - document-layout
14
  - onnx
15
- - netra-runtime
16
  - netra-lab
17
  ---
18
 
@@ -24,56 +23,58 @@ tags:
24
 
25
  <p align="center">
26
  <a href="https://github.com/netra-ai-lab/Netra-OCR"><b>GitHub</b></a> |
27
- <a href="https://github.com/netra-ai-lab/Netra-Runtime"><b>Netra Runtime</b></a> |
28
  <a href="https://pypi.org/project/netra-ocr/"><b>PyPI</b></a> |
29
  <a href="https://huggingface.co/Darayut/khmer-text-recognition"><b>PyTorch weights</b></a>
30
  </p>
31
 
32
  # Netra OCR
33
 
34
- The models behind the Netra OCR app, exported as [Netra Runtime](https://github.com/netra-ai-lab/Netra-Runtime) bundles: ONNX graphs plus a `netra-model.json` manifest that says how to pre-process, decode and post-process. The same bundles run on CPU and CUDA from Python and in the browser (WebGPU / WebAssembly), with no PyTorch.
35
 
36
- Each folder is one bundle:
37
 
38
- | Folder | Task | What it is | Variants |
39
- |---|---|---|---|
40
- | `recognition/` | text recognition | Khmer + English line recognizer, 19M params, greedy decoding with a KV cache | – |
41
- | `recognition-blockwise/` | text recognition | the same recognizer plus a blockwise proposal head (same output, fewer decoder passes) | – |
42
- | `lines/` | object detection | YOLO text-line and logo detector | `fp16` (CUDA default) |
43
- | `layout/` | object detection | DocLayout-YOLO (DocStructBench) page-layout analyzer | `fp16` (CUDA default) |
 
 
44
 
45
  ## Usage
46
 
47
  ```bash
48
- pip install "netra-runtime[cpu]" # or [gpu] for CUDA
49
  ```
50
 
51
  ```python
52
- import netra_runtime
53
 
54
- recognizer = netra_runtime.load("hf://Netra-Lab/Netra-OCR/recognition", device="auto")
55
  print(recognizer("line.png").text)
56
 
57
- detector = netra_runtime.load("hf://Netra-Lab/Netra-OCR/lines")
58
  for box in detector("page.png"):
59
  print(box.label, box.score, box.box)
60
  ```
61
 
62
  ```js
63
- import { load } from "@netra-ai-lab/runtime-web";
64
- const recognizer = await load("hf://Netra-Lab/Netra-OCR/recognition");
 
65
  const { text } = await recognizer.recognize(imageElement);
66
  ```
67
 
68
- `hf://` downloads only the folder you ask for, once, into the Hugging Face cache. For whole pages (detection, layout, reading order, Word/HTML/Markdown export) use the [`netra-ocr`](https://pypi.org/project/netra-ocr/) package or the Netra OCR Docker image, which load these bundles.
69
 
70
  ## Parity and speed
71
 
72
  Measured against the PyTorch models on `test_set/khob_eval` (325 lines) and 10 test pages, on an i7-13700KF and an RTX 3060.
73
 
74
  - **Recognizer:** text identical to PyTorch greedy decoding on 325/325 lines, on CPU and CUDA, single and batched. Per line: CPU 36.7 → about 13 ms, CUDA 23 → 12.8 ms.
75
- - **Blockwise:** identical text, 2.32 tokens per decoder pass. Not faster than the KV-cached greedy decoder on CPU or CUDA; faster on WebGPU (64 vs 86 ms per line).
76
- - **Full page pipeline:** CPU 2.18 → 1.14 s/page, GPU 1.24 → 0.70 s/page. 7 of 10 pages identical to the PyTorch pipeline, 0.43% characters different overall (letterbox resize is defined by the bundle spec rather than OpenCV, which moves about 1% of borderline boxes).
77
  - **fp16:** default on CUDA for the detectors (DocLayout 65 → 39 ms). Not used on WebGPU, where it is broken in onnxruntime-web 1.31.
78
  - **Browser:** WebAssembly gives the same text on 325/325 lines and detector boxes at IoU 1.0; WebGPU in Chrome gave the same text on 100/100 lines.
79
 
@@ -83,11 +84,11 @@ The recognizer's CER is the PyTorch model's: see [Darayut/khmer-text-recognition
83
 
84
  | File | Contents |
85
  |---|---|
86
- | `*/netra-model.json` | manifest: task, components, graphs, variants, sha256 of every file |
87
  | `*/*.onnx` | opset-18 graphs (`encoder`/`decoder_step` for recognition, `model` for detection) |
88
- | `recognition*/vocab.json` | tokenizer vocabulary (class names of the detectors are in the manifest) |
89
 
90
- The bundle format is specified in [Netra-Runtime/spec/bundle.md](https://github.com/netra-ai-lab/Netra-Runtime/blob/main/spec/bundle.md).
91
 
92
  ## License and attribution
93
 
 
12
  - khmer-ocr
13
  - document-layout
14
  - onnx
 
15
  - netra-lab
16
  ---
17
 
 
23
 
24
  <p align="center">
25
  <a href="https://github.com/netra-ai-lab/Netra-OCR"><b>GitHub</b></a> |
 
26
  <a href="https://pypi.org/project/netra-ocr/"><b>PyPI</b></a> |
27
  <a href="https://huggingface.co/Darayut/khmer-text-recognition"><b>PyTorch weights</b></a>
28
  </p>
29
 
30
  # Netra OCR
31
 
32
+ The models behind the Netra OCR app, exported to ONNX. Each folder holds the ONNX graphs plus a `netra-model.json` config with the settings the app's pre- and post-processing need (line height and chunk width, decoder shape, class names, thresholds). The [`netra-ocr`](https://pypi.org/project/netra-ocr/) package runs them on ONNX Runtime on CPU and CUDA, and its [`web/`](https://github.com/netra-ai-lab/Netra-OCR/tree/master/web) folder runs the same files in the browser (WebGPU / WebAssembly), with no PyTorch.
33
 
34
+ Each folder is one model:
35
 
36
+ | Folder | Task | What it is | Download | Variants |
37
+ |---|---|---|---|---|
38
+ | `recognition/` | text recognition | Khmer + English line recognizer, 19M params, greedy decoding with a KV cache | 41 MB | – |
39
+ | `recognition-blockwise/` | text recognition | the same recognizer plus a blockwise proposal head (same output, fewer decoder passes) | 44 MB | – |
40
+ | `lines/` | object detection | YOLO text-line and logo detector | 38 MB (19 MB on CUDA) | `fp16` (CUDA default) |
41
+ | `layout/` | object detection | DocLayout-YOLO (DocStructBench) page-layout analyzer | 39 MB | `fp16` (CUDA default) |
42
+
43
+ A full page pipeline on the CPU downloads about 118 MB. The recognizers' and the layout model's weights are *stored* in half precision and cast back to float32 when the model loads, so they run in float32 at the same speed; only the weights' rounding changes. On 325 test lines, the text matches the float32 files on 325/325 lines on the CPU and 321/325 on CUDA (on the other 4, the number of errors against the labels is unchanged). The layout model gives identical pages. The line detector stays float32, because half-precision storage moved boxes on 2 of 10 test pages.
44
 
45
  ## Usage
46
 
47
  ```bash
48
+ pip install "netra-ocr[cpu]" # or [gpu] for CUDA
49
  ```
50
 
51
  ```python
52
+ from netra_ocr.inference import Detector, Recognizer
53
 
54
+ recognizer = Recognizer("hf://Netra-Lab/Netra-OCR/recognition") # device: "auto" (default), "cpu", "cuda"
55
  print(recognizer("line.png").text)
56
 
57
+ detector = Detector("hf://Netra-Lab/Netra-OCR/lines")
58
  for box in detector("page.png"):
59
  print(box.label, box.score, box.box)
60
  ```
61
 
62
  ```js
63
+ // web/src/index.js in the Netra-OCR repo
64
+ import { loadRecognizer } from "./web/src/index.js";
65
+ const recognizer = await loadRecognizer("hf://Netra-Lab/Netra-OCR/recognition");
66
  const { text } = await recognizer.recognize(imageElement);
67
  ```
68
 
69
+ `hf://` downloads only the folder you ask for, and only the files your device runs, once, into the Hugging Face cache. For whole pages (detection, layout, reading order, Word/HTML/Markdown export) use `netra_ocr.KhmerOCRPipeline`, the `netra_ocr serve` web app or the Netra OCR Docker image.
70
 
71
  ## Parity and speed
72
 
73
  Measured against the PyTorch models on `test_set/khob_eval` (325 lines) and 10 test pages, on an i7-13700KF and an RTX 3060.
74
 
75
  - **Recognizer:** text identical to PyTorch greedy decoding on 325/325 lines, on CPU and CUDA, single and batched. Per line: CPU 36.7 → about 13 ms, CUDA 23 → 12.8 ms.
76
+ - **Blockwise:** identical text, 2.32 tokens per decoder pass. Not faster than the KV-cached greedy decoder on CPU, CUDA or WebGPU (82 vs 85 ms per line in Chrome).
77
+ - **Full page pipeline:** CPU 2.18 → 1.14 s/page, GPU 1.24 → 0.70 s/page. 7 of 10 pages identical to the PyTorch pipeline, 0.43% characters different overall (the letterbox resize is Netra OCR's own float64 bilinear resize rather than OpenCV's, which moves about 1% of borderline boxes).
78
  - **fp16:** default on CUDA for the detectors (DocLayout 65 → 39 ms). Not used on WebGPU, where it is broken in onnxruntime-web 1.31.
79
  - **Browser:** WebAssembly gives the same text on 325/325 lines and detector boxes at IoU 1.0; WebGPU in Chrome gave the same text on 100/100 lines.
80
 
 
84
 
85
  | File | Contents |
86
  |---|---|
87
+ | `*/netra-model.json` | config: pre/post-processing settings, graphs, precision variants, sha256 of every file |
88
  | `*/*.onnx` | opset-18 graphs (`encoder`/`decoder_step` for recognition, `model` for detection) |
89
+ | `recognition*/vocab.json` | tokenizer vocabulary (class names of the detectors are in the config) |
90
 
91
+ The Python reader is [`netra_ocr/inference/`](https://github.com/netra-ai-lab/Netra-OCR/tree/master/netra_ocr/inference); the exporters are in [`training/netra_ocr_train/scripts/`](https://github.com/netra-ai-lab/Netra-OCR/tree/master/training/netra_ocr_train/scripts).
92
 
93
  ## License and attribution
94
 
layout/model.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:e15787e894a211f64602e4efef59e1179e6d79f12f5b4f0734a00b32daf94e2d
3
- size 76930373
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:87b1b6b983f7120547342ab23d0564fb2b3766f23048a297590d73919aee8383
3
+ size 39405559
layout/netra-model.json CHANGED
@@ -48,6 +48,6 @@
48
  },
49
  "files": {
50
  "model.fp16.onnx": "6fbbe1a2d71b09f937e50b46b81adad0a54f06fcbae406a0fa3c2aafaa1585f2",
51
- "model.onnx": "e15787e894a211f64602e4efef59e1179e6d79f12f5b4f0734a00b32daf94e2d"
52
  }
53
  }
 
48
  },
49
  "files": {
50
  "model.fp16.onnx": "6fbbe1a2d71b09f937e50b46b81adad0a54f06fcbae406a0fa3c2aafaa1585f2",
51
+ "model.onnx": "87b1b6b983f7120547342ab23d0564fb2b3766f23048a297590d73919aee8383"
52
  }
53
  }
recognition-blockwise/decoder_step.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:73b934b9817f25e03cbd14bdf4260c3145dc9e4347ab77f4d9fd883b1d72279a
3
- size 33412682
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9333350eb3398dfd41cb9734755493e562d10c4dd221234df06e0ae2a3d3d55c
3
+ size 16785190
recognition-blockwise/encoder.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f58c6a10b9f5631492ded33641ae337c70300ec15f96b74b8b89adbb5c0c3bfb
3
- size 54400775
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a2b599925350e191c8dbc86126842cef7eb4b621a8e5ef276ce4b5d730beb9c6
3
+ size 27335904
recognition-blockwise/netra-model.json CHANGED
@@ -44,8 +44,8 @@
44
  "license": "MIT"
45
  },
46
  "files": {
47
- "decoder_step.onnx": "73b934b9817f25e03cbd14bdf4260c3145dc9e4347ab77f4d9fd883b1d72279a",
48
- "encoder.onnx": "f58c6a10b9f5631492ded33641ae337c70300ec15f96b74b8b89adbb5c0c3bfb",
49
  "vocab.json": "d55b8578e66dd4069f3abdaf01d0993f8526587dbebec78dcbcd15c514a6268b"
50
  }
51
  }
 
44
  "license": "MIT"
45
  },
46
  "files": {
47
+ "decoder_step.onnx": "9333350eb3398dfd41cb9734755493e562d10c4dd221234df06e0ae2a3d3d55c",
48
+ "encoder.onnx": "a2b599925350e191c8dbc86126842cef7eb4b621a8e5ef276ce4b5d730beb9c6",
49
  "vocab.json": "d55b8578e66dd4069f3abdaf01d0993f8526587dbebec78dcbcd15c514a6268b"
50
  }
51
  }
recognition/decoder_step.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:c24deade583d3a0085de6ae18ce99b5e2a6ad2f874ef7670bdc57c02c6f8f63e
3
- size 26311577
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:adf53d37dc558f562d2a1eddcde723d36eda2c2d922a6fe3c9864bbe51e12647
3
+ size 13227369
recognition/encoder.onnx CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f1c11222ae3e7363618b3e0ce14ad49de6b8332b70502228bf6eb03656e031fd
3
- size 54400037
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3e6c1b4984cdaf7578d9f591e1c3117df3b90c2a04fb2a18f274b19e4888c475
3
+ size 27335166
recognition/netra-model.json CHANGED
@@ -43,8 +43,8 @@
43
  "license": "MIT"
44
  },
45
  "files": {
46
- "decoder_step.onnx": "c24deade583d3a0085de6ae18ce99b5e2a6ad2f874ef7670bdc57c02c6f8f63e",
47
- "encoder.onnx": "f1c11222ae3e7363618b3e0ce14ad49de6b8332b70502228bf6eb03656e031fd",
48
  "vocab.json": "d55b8578e66dd4069f3abdaf01d0993f8526587dbebec78dcbcd15c514a6268b"
49
  }
50
  }
 
43
  "license": "MIT"
44
  },
45
  "files": {
46
+ "decoder_step.onnx": "adf53d37dc558f562d2a1eddcde723d36eda2c2d922a6fe3c9864bbe51e12647",
47
+ "encoder.onnx": "3e6c1b4984cdaf7578d9f591e1c3117df3b90c2a04fb2a18f274b19e4888c475",
48
  "vocab.json": "d55b8578e66dd4069f3abdaf01d0993f8526587dbebec78dcbcd15c514a6268b"
49
  }
50
  }