Expose the existing character branch for printed English
Browse filesAdd 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 +7 -3
- checksums.sha256 +4 -3
- predict.py +5 -3
- release-manifest.json +11 -1
- text-style-validation.json +42 -0
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
|
| 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 |
-
|
| 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 |
-
|
| 38 |
-
|
| 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
|
| 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 |
+
}
|