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 (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

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.

Exact-line accuracy of the int8 files of the main and tiny models

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.

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: non-commercial use only, credit this model and the datasets above, and share adaptations under the same license.

Training code (MIT): ErdemWilkinson/InviolusOCR.

Downloads last month
47
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support