Instructions to use inviolus/InviolusOCR with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Keras
How to use inviolus/InviolusOCR with Keras:
# !pip install -U keras tensorflow huggingface_hub # Keras needs TensorFlow installed to read "hf://" paths, so the tensorflow backend is selected here; # "jax" and "torch" also work for computation once TensorFlow is installed. import os os.environ["KERAS_BACKEND"] = "tensorflow" import keras model = keras.saving.load_model("hf://inviolus/InviolusOCR") - Notebooks
- Google Colab
- Kaggle
File size: 6,314 Bytes
ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 993b508 ef9f248 | 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 | ---
license: cc-by-nc-sa-4.0
language:
- tr
library_name: keras
pipeline_tag: image-to-text
tags:
- ocr
- text-recognition
- turkish
- tinyml
- tflite
- int8
- ctc
- microcontroller
---
# InviolusOCR: tiny Turkish line OCR for microcontrollers
A compact convolutional CTC recognizer for **one cropped line of printed
Turkish text**: 560,954 parameters and a **598 KB full-int8 TensorFlow Lite**
file that keeps almost all of the float model's accuracy. A half-width **tiny**
variant is **171 KB**.
*Keywords: Turkish OCR, Türkçe OCR, tiny OCR, text recognition, TFLite, int8,
TinyML, ESP32, microcontroller.*
> **Türkçe özet:** Mikrodenetleyiciler için tek satır Türkçe metin okuyan,
> 561 bin parametreli, int8 TFLite dosyası 598 KB olan küçük bir OCR modeli.
> int8 hâli, ayrılmış test satırlarının %77,3'ünü, gerçek sahne metni
> (TS-TR) kırpıntılarının %56,2'sini ve basılı belge satırlarının (donut)
> %46,5'ini harfi harfine doğru okuyor. 171 KB'lık küçük sürüm daha düşük
> doğrulukta çalışıyor (%64,4 / %32,6 / %20,1). Ticari olmayan kullanım içindir
> (CC BY-NC-SA 4.0).
This replaces [inviolus/erdem-ocr-tr-tinyml](https://huggingface.co/inviolus/erdem-ocr-tr-tinyml)
(2026-10-09), whose int8 file lost most of its accuracy.
## Files
| File | What it is |
|---|---|
| `inviolusocr.keras` | Float model, input `(batch, 32, 160, 1)`, output `(batch, 40, 90)` softmax |
| `inviolusocr_int8.tflite` | Full-int8 export, input `[1, 32, 160, 1]` int8 (scale 0.007843, zero point -1), output `[1, 40, 90]` int8 (scale 0.00390625, zero point -128) |
| `inviolusocr_tiny.keras`, `inviolusocr_tiny_int8.tflite` | Half-width variant, 144,330 parameters, same input, output and alphabet |
| `alphabet.json` | Character set used to decode the output |
| `benchmark.json`, `benchmark_T.json` | Scores for this model and the earlier versions; scores for tiny |
## Model
- **Input:** one horizontal text line, grayscale, resized to 160×32, scaled
to `[-1, 1]` (`pixel / 127.5 - 1`).
- **Architecture:** 4 conv + batch-norm + pool blocks, a dense projection,
then four residual dilated 1-D convolutions (dilation 1, 2, 4, 1) instead of
an LSTM, and a dense softmax. Only ops that quantize cleanly to int8.
- **Output:** 40 timesteps × 90 classes. Class `0` is padding, `1..88` are the
characters of `alphabet.json` in order, `89` is the CTC blank.
- **Character set:** digits, ASCII letters, `ç ğ ı İ ö ş ü Ç Ğ Ö Ş Ü`, space
and `.,:;!?-_/()'%`. Up to 24 characters per line.
- **Not included:** text detection. The line must already be cropped.
## Usage
```python
import json
import numpy as np
import tensorflow as tf
alphabet = json.load(open("alphabet.json", encoding="utf-8"))["alphabet"]
BLANK = len(alphabet) + 1
def preprocess(path):
image = tf.io.decode_image(tf.io.read_file(path), channels=1, expand_animations=False)
image = tf.image.resize(image, [32, 160])
return (tf.cast(image, tf.float32) / 127.5 - 1.0).numpy()
def decode(ids):
text, previous = [], None
for i in ids:
if i != previous and 0 < i < BLANK:
text.append(alphabet[i - 1])
previous = i
return "".join(text)
# int8 TFLite (the file meant for devices)
interpreter = tf.lite.Interpreter(model_path="inviolusocr_int8.tflite")
interpreter.allocate_tensors()
inp, out = interpreter.get_input_details()[0], interpreter.get_output_details()[0]
scale, zero = inp["quantization"]
x = np.clip(np.round(preprocess("line.png") / scale + zero), -128, 127).astype(np.int8)
interpreter.set_tensor(inp["index"], x[np.newaxis])
interpreter.invoke()
print(decode(interpreter.get_tensor(out["index"])[0].argmax(-1)))
```
## Results
Exact-line accuracy (the whole line correct), all models scored on the same
rows: 12,093 held-out lines (synthetic, Zenodo, TS-TR, esengul3, STS-TR) and
the 2,078-crop official TS-TR test split (real scene text, never trained on),
plus 2,563 printed-document rows from the donut 200k test list.

| Model, int8 file | Params | Size | Held-out | TS-TR | Donut test |
|---|---:|---:|---:|---:|---:|
| erdem-ocr 2026-10-09 (LSTM) | 631,226 | 665 KB | 32.9% | 33.5% | not measured |
| InviolusOCR 2026-10-31 (previous version here) | 560,954 | 598 KB | 78.4% | 58.2% | 9.3% |
| **InviolusOCR 2026-11-01 (main)** | **560,954** | **598 KB** | **77.3%** | **56.2%** | **46.5%** |
| **InviolusOCR tiny 2026-11-02** | **144,330** | **171 KB** | 64.4% | 32.6% | 20.1% |
Character error rate of the int8 files: main 10.0% held-out, 18.8% TS-TR, 12.6%
donut; tiny 14.1%, 31.3%, 24.1%.
## Limitations
- Printed text only; no handwriting, curved text or full pages.
- Real scene text is still the weak spot (56% exact).
- **Licence plates are not read** (2% exact on 250 plate crops in a first,
unchecked test).
- Not yet measured on a microcontroller (speed, memory).
- Text detection and line cropping must be done before this model runs.
## Training data
About 106,000 training crops. The main model was continued from earlier
weights; tiny was trained from scratch for 260 minutes on CPU.
- Synthetic Turkish lines rendered from a 50k-word Turkish word list.
- [Turkish OCR Text Image Dataset](https://zenodo.org/records/21923181), Zenodo, CC BY 4.0.
- [Turkish Scene Text Recognition (TS-TR)](https://www.kaggle.com/datasets/serdaryildiz/turkish-scene-text-recognition-dataset), Serdar Yıldız, CC BY-NC 4.0.
- [Synthetic Turkish Scene Text (STS-TR)](https://www.kaggle.com/datasets/serdaryildiz/synthetic-turkish-scene-text-recognition-dataset), Serdar Yıldız, CC BY-NC 4.0.
- [Turkish Word OCR](https://huggingface.co/datasets/esengul3/turkish-word-ocr), esengul3, CC BY-SA 4.0.
- Turkish recognition 200k v4 (donut), turgutguvercin, CC BY-SA 4.0.
## License
Because of the non-commercial (TS-TR, STS-TR) and share-alike (esengul3, donut)
terms of the training data, this model is released under
**[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)**:
non-commercial use only, credit this model and the datasets above, and share
adaptations under the same license.
Training code (MIT): [ErdemWilkinson/InviolusOCR](https://github.com/ErdemWilkinson/InviolusOCR).
|