voidash commited on
Commit
a73a515
·
verified ·
1 Parent(s): 92c5385

Expose the existing character branch for printed English

Browse files

Add an explicit handwriting/print CLI option, retaining the original handwriting default. Four actual source/Paddle input-style controls match saved references. Neural weights, native graphs and benchmark metrics are unchanged.

README.md CHANGED
@@ -48,10 +48,11 @@ hf download ampixa/deva-ocr-75m-research --local-dir deva-ocr-75m
48
  cd deva-ocr-75m
49
  pip install -r requirements-source.txt
50
  python predict.py /path/to/cropped-line.png --language ne
51
- python predict.py /path/to/english-line.png --language en
 
52
  ```
53
 
54
- The included CLI uses serial CPU inference and does not download another model. Choose `ne`, `hi` or `en` explicitly. Nepali and Hindi use the character decoder with the adapted encoder; English uses the unchanged original English model. All branches resize each crop to 384×384 RGB. Character decoding uses 10 beams and up to 257 new tokens; English uses 10 beams and up to 256. JSON output includes text, raw token IDs and whether generation reached its cap.
55
 
56
  This is a custom architecture. Use the included loader/CLI; `AutoModel.from_pretrained` and the generic Transformers OCR pipeline are not configured for this repository.
57
 
@@ -62,6 +63,7 @@ Install the native dependencies in a separate environment:
62
  ```bash
63
  pip install -r requirements-paddle.txt
64
  python predict.py /path/to/cropped-line.png --language ne --backend paddle
 
65
  ```
66
 
67
  The prebuilt operator library was validated on Linux x86_64 with FMA, PaddlePaddle 3.3.1 and PaddleX 3.7.1, using two CPU threads. Native GPU execution and other platforms are unvalidated. Use the source backend on platforms incompatible with the prebuilt library. The custom operator source and its third-party notices are under `paddle/code/`.
@@ -85,7 +87,7 @@ for result in predictor.predict("cropped-line.png", branch="character"):
85
  print(result["rec_text"])
86
  ```
87
 
88
- Use `branch="english"` for English. The research opt-in remains intentional: fixed-crop numerical parity does not establish full product acceptance. Scores are uncalibrated beam scores. Detection, reading order, word boxes, full-page segmentation and automatic language routing are not included.
89
 
90
  ## Architecture and provenance
91
 
@@ -100,3 +102,5 @@ Use is restricted to non-commercial research and education. Training includes re
100
  ## Release packaging checks
101
 
102
  The download-layout CLI was checked on fixed Nepali, Hindi and English inputs in both backends (six exact reference matches). The actual PaddleX factory was rerun on 24 path inputs and 24 BGR inputs, with 24 JSON results checked and zero Torch tensor operations. These are packaging controls; the larger fixed-corpus accuracy results are reported above.
 
 
 
48
  cd deva-ocr-75m
49
  pip install -r requirements-source.txt
50
  python predict.py /path/to/cropped-line.png --language ne
51
+ python predict.py /path/to/english-line.png --language en --text-style handwriting
52
+ python predict.py /path/to/printed-english.png --language en --text-style print
53
  ```
54
 
55
+ The included CLI uses serial CPU inference and does not download another model. Choose `ne`, `hi` or `en` explicitly. Set `--text-style print` for printed English; the default text style is `handwriting`. Nepali, Hindi and printed English use the character decoder with the adapted encoder. English handwriting uses the unchanged original English model. Text style is selected by the caller; the CLI does not detect it automatically. All branches resize each crop to 384×384 RGB. Character decoding uses 10 beams and up to 257 new tokens; English uses 10 beams and up to 256. JSON output includes text, raw token IDs and whether generation reached its cap.
56
 
57
  This is a custom architecture. Use the included loader/CLI; `AutoModel.from_pretrained` and the generic Transformers OCR pipeline are not configured for this repository.
58
 
 
63
  ```bash
64
  pip install -r requirements-paddle.txt
65
  python predict.py /path/to/cropped-line.png --language ne --backend paddle
66
+ python predict.py /path/to/printed-english.png --language en --text-style print --backend paddle
67
  ```
68
 
69
  The prebuilt operator library was validated on Linux x86_64 with FMA, PaddlePaddle 3.3.1 and PaddleX 3.7.1, using two CPU threads. Native GPU execution and other platforms are unvalidated. Use the source backend on platforms incompatible with the prebuilt library. The custom operator source and its third-party notices are under `paddle/code/`.
 
87
  print(result["rec_text"])
88
  ```
89
 
90
+ Use `branch="english"` for English handwriting and `branch="character"` for printed English, Nepali and Hindi. The research opt-in remains intentional: fixed-crop numerical parity does not establish full product acceptance. Scores are uncalibrated beam scores. Detection, reading order, word boxes, full-page segmentation and automatic language routing are not included.
91
 
92
  ## Architecture and provenance
93
 
 
102
  ## Release packaging checks
103
 
104
  The download-layout CLI was checked on fixed Nepali, Hindi and English inputs in both backends (six exact reference matches). The actual PaddleX factory was rerun on 24 path inputs and 24 BGR inputs, with 24 JSON results checked and zero Torch tensor operations. These are packaging controls; the larger fixed-corpus accuracy results are reported above.
105
+
106
+ The explicit text-style CLI update was checked on one fixed English handwriting input and one fixed printed-English input in both Torch and Paddle. All four token/text/cap outputs matched their existing source references. See `text-style-validation.json`. This update retains all neural weights, native graphs, original benchmark records and default handwriting behavior.
checksums.sha256 CHANGED
@@ -1,6 +1,6 @@
1
  50afebf8ea7728756aa97b425f84db6b8137e791c0c8f8bdcc46c533e940beb3 .gitattributes
2
  37908899ed8fb456bd644323faae79bdd5b54ebdf90f07c7cf795d5ccfdd2866 LICENSE
3
- fc0aee088bfeb7f7449f98426a6a8185e1b81e767da6da45b13016bf687fdbd6 README.md
4
  3beebf852bf869560dd1adabeb93be212c61a55ce002fbe2bdea2b5f8167cb68 THIRD_PARTY_NOTICES.md
5
  d986e14af668016c081480cb05e316987bc8c519764f9f004c33db66e855a5d5 TRAINING_DATA.md
6
  0498d8b7d61f3c8e4a4fdcd927a507464cfaf8156bf874a211484a5474697719 code/shared_character_recognizer.py
@@ -34,8 +34,8 @@ b2a632ecd78bd35441f0575b5073ebdfe2dd8edebff08c892b386205655700b0 paddle/encoder
34
  6e19e7fe532e7d24d504f9e323e08d5c77e1ca07ceaeb1ebcc0f616369834dbc paddle/encoder/report.json
35
  42c4cf89a86fc3de900949348079f7b0c90d4e58ca2d28a105e326785a3eacd5 paddle/encoder/run.json
36
  4748d485e0280227d6b395faf8c0b956217389abb4a3c267ff6cf5d427116863 paddle/inference.yml
37
- ec18fa5c8940fee3624d1c05e0ea4be12f1f3105a184eb03f18e7b1991a8ee7c predict.py
38
- 0f20efb6a6b119ea4de9752b6120a19df0274c1c52621e6349e466b64b7a714b release-manifest.json
39
  7b26b16767a3a722eaed9b6499b3872927773a0817298bf8013a590c89e0e0bc requirements-paddle.txt
40
  2d2115dd37ef7dec5f883532694a7508120fe1fe20933d66bd843ff961460edf requirements-source.txt
41
  0510d21cd0bb7a249dafac167fd2e371ee63bd6f83a016a6c4f2e7c6bb843ede source-model/bundle.json
@@ -54,4 +54,5 @@ e098c98c6834fbcd3f3e75215e3e8b8868f0fe5bf07aef93d28e4f7196db293c source-model/e
54
  cddf3683b66672c43fee2a6d966829eebf2a00c61d376d0eb30db972693210be source-model/english-generation.json
55
  1c598da84fcbe26af738d5ef1c0ea04f80f965e7690b1089aeaa8c7977cd4359 source-model/model-configs.json
56
  9b58d252978d3a5d33adcdaea95e113162daf5146e20a9e1b8aa47e21e48ed93 source-model/weights.safetensors
 
57
  bf281f9f2fbabbec2885fc0556e59cc528bd2eed5f7033c20dd718bb480d9249 validation.json
 
1
  50afebf8ea7728756aa97b425f84db6b8137e791c0c8f8bdcc46c533e940beb3 .gitattributes
2
  37908899ed8fb456bd644323faae79bdd5b54ebdf90f07c7cf795d5ccfdd2866 LICENSE
3
+ e57a2acc8ac1c0bf86d0bc1c3477a9524faf5075e0de083ebe8275352ffd069e README.md
4
  3beebf852bf869560dd1adabeb93be212c61a55ce002fbe2bdea2b5f8167cb68 THIRD_PARTY_NOTICES.md
5
  d986e14af668016c081480cb05e316987bc8c519764f9f004c33db66e855a5d5 TRAINING_DATA.md
6
  0498d8b7d61f3c8e4a4fdcd927a507464cfaf8156bf874a211484a5474697719 code/shared_character_recognizer.py
 
34
  6e19e7fe532e7d24d504f9e323e08d5c77e1ca07ceaeb1ebcc0f616369834dbc paddle/encoder/report.json
35
  42c4cf89a86fc3de900949348079f7b0c90d4e58ca2d28a105e326785a3eacd5 paddle/encoder/run.json
36
  4748d485e0280227d6b395faf8c0b956217389abb4a3c267ff6cf5d427116863 paddle/inference.yml
37
+ c0a395b5e61144a0ae4391646bdeacc36da0842ad146f5fbf1b1cd4fc45927c8 predict.py
38
+ 933f75337532279f652fdca58cbb676af905546833c3941d1e85a07ea6e68e51 release-manifest.json
39
  7b26b16767a3a722eaed9b6499b3872927773a0817298bf8013a590c89e0e0bc requirements-paddle.txt
40
  2d2115dd37ef7dec5f883532694a7508120fe1fe20933d66bd843ff961460edf requirements-source.txt
41
  0510d21cd0bb7a249dafac167fd2e371ee63bd6f83a016a6c4f2e7c6bb843ede source-model/bundle.json
 
54
  cddf3683b66672c43fee2a6d966829eebf2a00c61d376d0eb30db972693210be source-model/english-generation.json
55
  1c598da84fcbe26af738d5ef1c0ea04f80f965e7690b1089aeaa8c7977cd4359 source-model/model-configs.json
56
  9b58d252978d3a5d33adcdaea95e113162daf5146e20a9e1b8aa47e21e48ed93 source-model/weights.safetensors
57
+ 4f65dbd06afb0d2da8f264337ac32ca37684f8863ebf5a7b0e42e0f41c268a74 text-style-validation.json
58
  bf281f9f2fbabbec2885fc0556e59cc528bd2eed5f7033c20dd718bb480d9249 validation.json
predict.py CHANGED
@@ -1,4 +1,4 @@
1
- """Recognize one cropped word or line with an explicit language branch."""
2
  import argparse
3
  import json
4
  from pathlib import Path
@@ -9,11 +9,13 @@ def main():
9
  parser = argparse.ArgumentParser(description=__doc__)
10
  parser.add_argument('image', type=Path)
11
  parser.add_argument('--language', choices=['ne', 'hi', 'en'], required=True)
 
 
12
  parser.add_argument('--backend', choices=['torch', 'paddle'], default='torch')
13
  parser.add_argument('--model-dir', type=Path, default=Path(__file__).resolve().parent)
14
  args = parser.parse_args()
15
  root = args.model_dir.resolve()
16
- branch = 'english' if args.language == 'en' else 'character'
17
  if args.backend == 'torch':
18
  import torch
19
  from PIL import Image
@@ -53,7 +55,7 @@ def main():
53
  allow_unqualified=True, library_path=folder / 'encoder-library.so')
54
  with Image.open(args.image) as image:
55
  result = model.predict_pixels(preprocess_rgb(image), branch)
56
- print(json.dumps(dict(language=args.language, branch=branch, backend=args.backend, **result), ensure_ascii=False))
57
 
58
 
59
  if __name__ == '__main__':
 
1
+ """Recognize one cropped word or line with an explicit language and text style."""
2
  import argparse
3
  import json
4
  from pathlib import Path
 
9
  parser = argparse.ArgumentParser(description=__doc__)
10
  parser.add_argument('image', type=Path)
11
  parser.add_argument('--language', choices=['ne', 'hi', 'en'], required=True)
12
+ parser.add_argument('--text-style', choices=['handwriting', 'print'], default='handwriting',
13
+ help='English print uses the character branch; default: handwriting.')
14
  parser.add_argument('--backend', choices=['torch', 'paddle'], default='torch')
15
  parser.add_argument('--model-dir', type=Path, default=Path(__file__).resolve().parent)
16
  args = parser.parse_args()
17
  root = args.model_dir.resolve()
18
+ branch = 'english' if args.language == 'en' and args.text_style == 'handwriting' else 'character'
19
  if args.backend == 'torch':
20
  import torch
21
  from PIL import Image
 
55
  allow_unqualified=True, library_path=folder / 'encoder-library.so')
56
  with Image.open(args.image) as image:
57
  result = model.predict_pixels(preprocess_rgb(image), branch)
58
+ print(json.dumps(dict(language=args.language, text_style=args.text_style, branch=branch, backend=args.backend, **result), ensure_ascii=False))
59
 
60
 
61
  if __name__ == '__main__':
release-manifest.json CHANGED
@@ -11,5 +11,15 @@
11
  "complete_preexisting_native_source_comparison_images": 8796,
12
  "packaged_conversion_predictions": false,
13
  "packaged_training_data": false,
14
- "published_use_scope": "non-commercial research and education; see LICENSE and TRAINING_DATA.md"
 
 
 
 
 
 
 
 
 
 
15
  }
 
11
  "complete_preexisting_native_source_comparison_images": 8796,
12
  "packaged_conversion_predictions": false,
13
  "packaged_training_data": false,
14
+ "published_use_scope": "non-commercial research and education; see LICENSE and TRAINING_DATA.md",
15
+ "default_text_style": "handwriting",
16
+ "explicit_text_styles": [
17
+ "handwriting",
18
+ "print"
19
+ ],
20
+ "English_handwriting_branch": "english",
21
+ "English_print_branch": "character",
22
+ "prediction_entrypoint_sha256": "c0a395b5e61144a0ae4391646bdeacc36da0842ad146f5fbf1b1cd4fc45927c8",
23
+ "text_style_validation_sha256": "4f65dbd06afb0d2da8f264337ac32ca37684f8863ebf5a7b0e42e0f41c268a74",
24
+ "text_style_update_neural_artifacts_unchanged": true
25
  }
text-style-validation.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checked_UTC": "2026-10-25T02:03:39.545714+00:00",
3
+ "candidate_predict_sha256": "c0a395b5e61144a0ae4391646bdeacc36da0842ad146f5fbf1b1cd4fc45927c8",
4
+ "published_release_files_verified_before_inference": 57,
5
+ "candidate_manifest_sha256": "0510d21cd0bb7a249dafac167fd2e371ee63bd6f83a016a6c4f2e7c6bb843ede",
6
+ "default_handwriting_behavior_retained": true,
7
+ "printed_English_uses_existing_character_branch": true,
8
+ "controls": [
9
+ {
10
+ "text_style": "handwriting",
11
+ "backend": "torch",
12
+ "branch": "english",
13
+ "input_image_sha256": "0e8a9d7d4d9e4fded67ad2ea434f0176fbb06d032f63cc572750cc9a75981cf3",
14
+ "tokens_text_caps_match_saved_source": true
15
+ },
16
+ {
17
+ "text_style": "handwriting",
18
+ "backend": "paddle",
19
+ "branch": "english",
20
+ "input_image_sha256": "0e8a9d7d4d9e4fded67ad2ea434f0176fbb06d032f63cc572750cc9a75981cf3",
21
+ "tokens_text_caps_match_saved_source": true
22
+ },
23
+ {
24
+ "text_style": "print",
25
+ "backend": "torch",
26
+ "branch": "character",
27
+ "input_image_sha256": "504ecd9fd45d54e340cdb2cf6872703e58af67769aa6ba70f9553cf76cf97606",
28
+ "tokens_text_caps_match_saved_source": true
29
+ },
30
+ {
31
+ "text_style": "print",
32
+ "backend": "paddle",
33
+ "branch": "character",
34
+ "input_image_sha256": "504ecd9fd45d54e340cdb2cf6872703e58af67769aa6ba70f9553cf76cf97606",
35
+ "tokens_text_caps_match_saved_source": true
36
+ }
37
+ ],
38
+ "model_weights_changed": false,
39
+ "native_graphs_changed": false,
40
+ "automatic_style_detection": false,
41
+ "full_domain_router_qualified": false
42
+ }