File size: 11,239 Bytes
c330961
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
---
license: other
license_name: proprietary-sciencesoft
license_link: https://huggingface.co/ScienceSoft/scnsoft-ocr-rec-multilingual/blob/main/README.md#licence
language: [en, ru, de, fr, es, it, ar]
pipeline_tag: image-to-text
tags: [ocr, text-recognition, pp-ocr, paddleocr-compatible, rapidocr, onnx, ctc, multilingual, cyrillic, arabic, rtl, gcc, mrz, dlp, pii]
library_name: onnxruntime
---

# ScienceSoft multilingual OCR recogniser (en · ru · de · fr · es · it · ar)

One **text-line recogniser** for printed Latin, Cyrillic and Arabic text in seven
languages, including identity-document text — passport / ID-card MRZ lines and
field labels, and the identity documents of the Gulf states (UAE, Saudi Arabia,
Qatar, Kuwait, Bahrain, Oman). It is the recognition half of the OCR step in a
data-loss-prevention agent that reads text in images leaving a device, so
personal data in a screenshot can be found and redacted before it reaches an AI
assistant.

- **PP-OCR mobile architecture** (PPLCNetV3 backbone + SVTR neck + CTC head),
  1.97 M parameters, re-implemented and trained in PyTorch, exported to ONNX.
- **Drop-in for PP-OCR-style pipelines**: same input/output contract as a
  PaddleOCR recognition model exported to ONNX, so it runs in
  [RapidOCR](https://github.com/RapidAI/RapidOCR) or PaddleOCR's ONNX mode with
  your own detector (see *Usage*).
- **`rec-multi.onnx`: int8 (static QDQ, convolutions only, percentile-calibrated),
  3.2 MB**, CPU. `rec-multi.fp32.onnx` (7.9 MB) is the float twin — use it for
  further conversion (e.g. X2Paddle) or fine-tuning.
- **659-entry dictionary**: Latin incl. French/German/Spanish/Italian letters, full
  Cyrillic, Arabic letters (plus پ چ ژ گ ک ی ڤ for names and loanwords), Western and
  Arabic-Indic digits, punctuation (incl. ، ؛ ؟ ٪), currency and typographic symbols.

It is a recogniser only: it reads one cropped text line. Pair it with a text
detector (e.g. PP-OCR DB).

Not affiliated with or endorsed by PaddlePaddle/Baidu; "PP-OCR" names the
architecture it follows.

## Input / output

| | |
|---|---|
| input `x` | `float32 [N, 3, 48, W]`, **BGR**, `(pixel/255 − 0.5) / 0.5`; resize the line crop to height 48 keeping aspect, right-pad with `0.0` (after normalisation). Trained with W padded to **960**; dynamic W works. |
| output `probs` | `float32 [N, W/8, 661]`, softmax over `[blank, dict..., " "]` |
| decode | greedy CTC: argmax per step, collapse repeats, drop blank (index 0); index `i` → `dict[i-1]`, index 660 → space |

### Arabic comes out in DRAWN order — reorder it

A CTC recogniser reads left to right, so an Arabic line is emitted in the order
its characters are drawn: `الاسم: محمد` comes out `دمحم :مسالا`. Put it back in
written order after decoding. PaddleOCR does this only when the dictionary file
name contains `arabic`, which `dict-multi.txt` does not — and its `pred_reverse`
leaves the separator in the wrong place (`الاسم :محمد`). This does it for one
line, as a renderer following the Unicode bidi algorithm (UAX #9) draws it:

```python
import re
L = "A-Za-zÀ-ɏЀ-ӿ"                  # Latin + Cyrillic letters
D = "0-9٠-٩۰-۹"                     # Western + Arabic-Indic digits
A = "ؠ-يٮ-ۓە"                  # Arabic letters
_ar, _strong, _letter = re.compile(f"[{A}]"), re.compile(f"[{A}{L}]"), re.compile(f"[{L}]")
_ltr_run = re.compile(f"[{L}{D}](?:[^{A}]*[{L}{D}])?")
_ar_run = re.compile(f"[{A}](?:[^{L}{D}]*[{A}])?")
_number = re.compile(f"[{D}]+(?:[.,:/ ٫٬][{D}]+)*")
_mirror = str.maketrans("()[]{}<>«»", ")(][}{><»«")

def _ltr_back(run):
    if _letter.search(run):                              # Latin text keeps its own order
        return run[::-1].translate(_mirror)
    return _number.sub(lambda m: m.group()[::-1], run)   # after Arabic, each number is its own run

def to_written_order(drawn: str) -> str:
    if not _ar.search(drawn):
        return drawn                                     # Latin / Cyrillic: unchanged
    if _ar.match(_strong.findall(drawn)[-1]):            # rightmost letter Arabic: a right-to-left line
        return _ltr_run.sub(lambda m: _ltr_back(m.group()), drawn[::-1].translate(_mirror))
    return _ar_run.sub(lambda m: m.group()[::-1], drawn) # a left-to-right line with Arabic words

to_written_order("1-1234567-1990-784 :ةيوهلا مقر")      # 'رقم الهوية: 784-1990-1234567-1'
```

It guesses the line's direction from the drawing: a left-to-right line that
*ends* in Arabic (`Name: محمد` in an English form) comes back as if it were
right-to-left. The ai-firewall runtime (`rust/ocr-core/src/bidi.rs`) has the same
limit; both put 12 of 14 mixed test lines back exactly, the other two being that
case.

## Usage

### RapidOCR (PaddleOCR's ONNX port) — verified

```python
# pip install rapidocr_onnxruntime==1.4.4 opencv-python-headless
from huggingface_hub import hf_hub_download
from rapidocr_onnxruntime import RapidOCR

repo = "ScienceSoft/scnsoft-ocr-rec-multilingual"
engine = RapidOCR(
    rec_model_path=hf_hub_download(repo, "rec-multi.onnx"),
    rec_keys_path=hf_hub_download(repo, "dict-multi.txt"),
)
result, _ = engine("screenshot.png")
for box, text, score in result or []:
    print(f"{score:.2f}  {text}")   # Arabic: see "drawn order" above
```

### onnxruntime directly (one cropped line)

See [`examples/onnxruntime_line.py`](examples/onnxruntime_line.py) — preprocessing
and CTC decoding in ~40 lines of numpy.

### PaddleOCR 2.x ONNX mode

`use_onnx=True`, `rec_model_dir=rec-multi.onnx`, `rec_char_dict_path=dict-multi.txt`,
`use_space_char=True`, `rec_image_shape="3,48,320"`. Same contract as RapidOCR;
not separately verified. A native Paddle (`.pdmodel`) version is not provided.

## Versions

- **r4** (this revision, 2026-10-02): adds Arabic — Modern Standard Arabic and
  seven dialects, Gulf identity documents, right-to-left interfaces. Fine-tuned
  from r3 for 30 k steps.
- **r3** (2026-09-30, not published separately): detector crops at DB unclip
  ratio 1.5, browser-rendered screenshot text, OCR-B MRZ.
- **r2** (git tag `r2`): the first release, trained for a tighter 2 px crop.

## Training

- **Data: 12.6 M line images** of printed text in the seven languages — document
  layouts, prose, interface text rendered by a real browser at 1×–2×, identity-document
  text (MRZ in ICAO 9303 TD1/TD2/TD3 with valid check digits, ID-card fields), Gulf
  identity documents (numbers that pass the issuers' checks; Hijri and Gregorian dates in
  Western and Arabic-Indic digits) and Arabic interfaces laid out right to left, across
  ~170 font faces. **All personal-data values are synthetic.** The training data is not
  published.
- **Crops match a real detector:** drawn from offsets measured between ground-truth
  boxes and a PP-OCRv3 DB detector's boxes (85 % at unclip ratio 1.5, 15 % at a
  tight 2 px expansion).
- Batch 256, AdamW + cosine, bf16, every batch at width 960, one NVIDIA DGX Spark
  (GB10). BatchNorm statistics re-estimated before every evaluation. The checkpoint
  was chosen on 34 separate validation sets, in fp32.

## Evaluation

End to end (PP-OCRv3 DB detector, unclip ratio 1.5 → this recogniser → written
order), character error rate, on **held-out synthetic sets**. Baselines are
PaddleOCR recognisers (ONNX) through the identical pipeline — PP-OCRv5 mobile for
Latin/Cyrillic, PP-OCRv3 for Arabic (the Arabic one available as ONNX).

**Arabic**

| eval set | PP-OCRv3 arabic | **r4** |
|---|---|---|
| prose: MSA / Najdi / Egyptian | 0.178 / 0.177 / 0.178 | **0.068 / 0.066 / 0.074** |
| prose: Levantine / Iraqi / Maghrebi | 0.173 / 0.208 / 0.176 | **0.075 / 0.076 / 0.065** |
| Arabic UI pages, unseen fonts | 0.206 | **0.097** |
| Gulf ID documents (6 states) | 0.082–0.106 | **0.018–0.024** (91–93 % of lines exact) |
| MRZ lines on Gulf documents, exact | 0.00 | **0.52–0.71** |

**Latin / Cyrillic**

| eval set | best PP-OCRv5 per language | r3 | **r4** |
|---|---|---|---|
| rendered en / de / es / fr / it | 0.024 / 0.030 / 0.022 / 0.023 / 0.040 | 0.019 / 0.022 / 0.015 / 0.024 / 0.034 | **0.016 / 0.018 / 0.011 / 0.017 / 0.029** |
| rendered ru | 0.058 | 0.028 | **0.027** |
| document-layout lines en / ru | **0.185** / 0.382 | 0.209 / 0.265 | 0.190 / **0.262** |
| ID-card mock-ups en / de / es / fr / it / ru | 0.050 / 0.046 / 0.062 / 0.058 / 0.043 / 0.093 | 0.046 / 0.027 / 0.040 / 0.037 / 0.024 / 0.049 | 0.057 / 0.029 / 0.042 / 0.036 / 0.024 / 0.071 |
| web pages, unseen fonts | 0.118 | 0.069 | **0.061** |

r4 beats the best per-language PP-OCRv5 model on 13 of 15 Latin/Cyrillic sets and
the PP-OCRv3 Arabic model on all 13 Arabic sets (mean 0.144 → 0.050). The int8
file is within 0.002 CER of its fp32 twin on these sets.

**Read these numbers for what they are:** every set is synthetic and comes from the
same kinds of sources the model was trained on (held-out samples, not held-out
sources), while the PaddleOCR models saw none of them — that favours this model.
The checkpoint was chosen on separate validation pages. The model has **not** been
benchmarked on real scanned or photographed documents or real screenshots.

## Limitations

- Evaluated on synthetic data only (see above).
- **Arabic output is drawn order** — reorder it (see above).
- **Latin/Cyrillic ID cards read worse than r3** (en 0.057 vs 0.046, ru 0.071 vs
  0.049): small ALL-CAPS lines (under ~20 px) are often read partly or wholly
  in lower case (`ВОДИТЕЛЬСКОЕ` → `водительСкое`). Mixed-case text is not
  affected.
- **MRZ**: 48–71 % of lines read exactly (monospace faces); 22 % in OCR-B. Do not
  rely on it for identity verification.
- Arabic: more tokens fall under a 0.9 confidence threshold than in Latin text, so a
  consumer that redacts low-confidence tokens over-masks Arabic more.
- Trained for crops at DB unclip ratio ~1.5 (PaddleOCR's default).
- Printed text only; no handwriting. Horizontal lines only (trained ≤ 2° tilt).
- A line longer than ~110 characters exceeds the 120 CTC steps at width 960.
- No CJK, Greek, Hebrew, Persian/Urdu-specific letters beyond those listed, or
  other scripts.

## Intended use

Reading printed text in screenshots and documents, in particular to find personal
data for redaction. Not intended for decisions about individuals (e.g. identity
verification).

## Licence

Proprietary to ScienceSoft. The weights, the dictionary and the example code are
published so that the results on this page can be evaluated and reproduced; no licence
to use them in production, to modify them or to redistribute them is granted. For
licensing, contact ScienceSoft (https://www.scnsoft.com).

The network follows the PP-OCR mobile text-recognition architecture described by the
PaddleOCR project (Apache-2.0, https://github.com/PaddlePaddle/PaddleOCR). It was
re-implemented and trained independently; no PaddleOCR weights were used.

## Citation

```bibtex
@misc{sciencesoft2026ocrmultilingual,
  title  = {ScienceSoft multilingual OCR recogniser (en, ru, de, fr, es, it, ar)},
  author = {{ScienceSoft}},
  year   = {2026},
  url    = {https://huggingface.co/ScienceSoft/scnsoft-ocr-rec-multilingual}
}
```