Зміст
Коли кажуть «OCR», зазвичай уявляють друкований текст: договір, рахунок, скан паспорта. Рукописні цифри в комірці таблиці — інша задача: інший шум, інший алфавіт, інша постановка. Одна картинка може означати клас 7, а може — рядок 783. Від формулювання залежить, чи потрібен простий класифікатор, CRNN з CTC чи повноцінний TrOCR.
Нижче — практичний розбір для інженерів, які будують розпізнавання на реальних фотографіях бланків, а не на датасеті MNIST. Ми пройдемо шлях від геометрії документа до порівняння архітектур, розберемо, як отримати розмітку з бази даних, і покажемо, чому найбільша модель рідко виявляється найкращим першим кроком. Матеріал доповнює контур OCR у завантаженні документів для RAG — там фокус на корпоративних PDF, тут — на вузькій, але типовій задачі польового вводу.
Ключові висновки
OCR — не одна задача. Класифікація однієї цифри та розпізнавання послідовності потребують різних моделей, метрик і даних.
Структура документа важливіша за нейромережу. Якщо шаблон бланка відомий, спочатку вирівнюєте геометрію і ріжете комірки — а не віддаєте цілу сторінку універсальному OCR.
Найкращий датасет — production-подібний. Висока точність на MNIST не переноситься на фотографії з перспективою, тінями та лініями таблиці.
Розмітка з бази може бути ціннішою за ручну. Коли фото пов’язане з записом у системі, ground truth уже є — лишається побудувати конвеєр cell image → label.
CNN — сильний baseline. Для однієї цифри у відомій комірці маленька згорткова мережа часто швидша, дешевша й зрозуміліша, ніж Transformer.
CRNN + CTC — природний крок для послідовностей. Кілька цифр у комірці без посимвольної розмітки — класична постановка Connectionist Temporal Classification.
TrOCR виправданий не завжди. Універсальна модель має сенс при складному тексті та розширенні алфавіту; для десяти цифр у фіксованій комірці спеціалізоване рішення часто виграє.
Production — це пайплайн. Детекція документа, корекція перспективи, правила валідації та human-in-the-loop не менш важливі, ніж вибір архітектури.
Дві різні задачі під одним словом «OCR»
Перш ніж порівнювати CNN і TrOCR, зафіксуйте, що саме ви розпізнаєте.
Класифікація зображення
Одна обрізана комірка містить одну цифру: картинка [ 7 ] → клас 7. Це класифікація на 10 класів (0–9). Модель видає розподіл ймовірностей за фіксованим набором міток. Довжина відповіді завжди дорівнює одному символу.
Така постановка можлива, коли шаблон бланка гарантує: у конкретному полі завжди одна цифра, або ви заздалегідь ріжете область так, що в кадрі лишається один символ.
Розпізнавання послідовності
Інша комірка містить кілька цифр: [ 7 8 3 ] → рядок "783". Модель повинна визначити символи, їхній порядок і кількість. Кількість класів на виході більше не фіксована одним числом — потрібен механізм декодування послідовності.
Це принципово інша задача. Класифікатор, навчений на окремих цифрах, не «додумає» порядок трьох символів без окремого етапу сегментації. А сегментація рукописних цифр на реальному бланку — окрема головний біль.
Чому MNIST — поганий проксі для реальних бланків
MNIST — 60 000 навчальних зображень рукописних цифр, 10 класів, одна цифра на картинку, нормалізований розмір 28×28, контрольовані умови зйомки. Для навчання основ computer vision датасет чудовий. Для обіцянок замовнику — небезпечний.
Реальні фотографії заповнених бланків додають фактори, яких у MNIST немає:
| Фактор | Що ламає |
|---|---|
| Перспектива і поворот | Цифра спотворена, пропорції не збігаються з навчальною вибіркою |
| Нерівномірне освітлення | Тіні, відблиски, локальний контраст |
| Сітка таблиці | Лінії перетинають штрихи цифр |
| Фон паперу | Текстура, плями, згини |
| Різна товщина пера | Тонкі й жирні штрихи в одному датасеті |
| Різні почерки й розміри | Один і той самий клас 3 виглядає по-різному |
| Якість камери | Шум, розмиття, стиснення JPEG |
Це domain gap: модель, натренована на MNIST, може показати 99% accuracy на тесті датасету і провалитися на фотографіях з телефона оператора.
Головний принцип простий: найкращий датасет для вашої задачі — дані, максимально схожі на production. Якщо в проді — фото бланків з полів, тренувальна вибірка повинна складатися з таких же фото, а не з нормалізованих гліфів 28×28.
Перший етап OCR — не нейромережа
Типова помилка — одразу шукати «найкращу OCR-модель» і віддавати їй цілу фотографію. На структурованих бланках виграє інший порядок:
фотографія → виявлення бланка → корекція перспективи →
прив’язка до шаблону → виділення комірок → попередня обробка → OCR
Чому відомий шаблон — величезна перевага
Якщо форма бланка фіксована:
- координати полів відомі заздалегідь або обчислюються після вирівнювання;
- рядки й стовпці таблиці передбачувані;
- не потрібно розпізнавати всю сторінку цілком.
Замість фотографія → велика OCR-модель → весь текст працює схема фотографія → geometry → cell → маленька OCR-модель. Кожна комірка — окремий вхід з маленьким алфавітом і обмеженою довжиною. Задача спрощується на порядок.
Це той самий інженерний прийом, що й у промисловому завантаженні документів: спочатку структура й канон, потім витяг сенсу. Для бланків «канон» — вирівняне зображення з вирізаними комірками.
OCR лише там, де він потрібен
Універсальний OCR по всій сторінці витрачає обчислення на заголовки, підписи, друкований текст і порожні поля. На фіксованому шаблоні розумніше:
- Знайти кути бланка (контури, маркери, QR).
- Застосувати гомографію — вирівняти перспективу.
- Накласти маску шаблону.
- Вирізати лише комірки з рукописними показниками.
- Запустити вузьку модель на кожній комірці.
Найцінніша частина — ground truth
Без чесної розмітки будь-який експеримент з архітектурами — порівняння шуму.
Звідки взяти правильні відповіді
У багатьох прикладних системах фотографія бланка вже пов’язана з записом у базі. Оператор сфотографував показання лічильника, а правильне значення лежить у таблиці readings. Або диспетчер ввів дані вручну після дзвінка — і фото слугує підтвердженням.
У такому разі розмітка не потребує армії розмітників. Потрібен конвеєр:
фотографія → ідентифікація бланка/сесії → запит у БД →
правильне значення поля → пара (cell image, label)
Приклади:
cell_00001.png → "78"cell_00002.png → "73"cell_00003.png → "71"
Чому це краще за ручну розмітку
- Масштаб: тисячі прикладів збираються автоматично в міру роботи системи.
- Менше помилок: людина не переписує цифри вручну в окремий файл.
- Актуальність: датасет оновлюється разом із потоком документів.
- Зв’язок із бізнес-контекстом: мітки відповідають тому, що система вважає істиною.
Застереження: ground truth з БД чесний лише якщо запис у базі дійсно вірний. Якщо оператори систематично помиляються при вводі, модель вивчить ті самі помилки.
Data leakage — тихий вбивця метрик
При розбитті train/validation/test не можна випадково змішувати:
- різні кропи одного й того ж бланка;
- фотографії однієї людини з майже ідентичним почерком;
- серії знімків, зроблених в однакових умовах освітлення.
Випадкове перемішування комірок без групування завищує метрики. Групуйте за документом, автором, сесією зйомки або датою — залежно від того, що реально «нове» в production.
Підхід до оцінки якості ШІ-систем загалом — у матеріалі «Оцінка корпоративного ШІ»; для OCR критичні саме групові спліти та метрики на рівні послідовності.
Перша модель — CNN як baseline
Convolutional Neural Network — згорткова нейромережа. Для задачі «одна цифра в комірці» це природна відправна точка.
Як CNN бачить цифру
Ієрархія ознак типова:
- Нижні шари — краї, лінії, кути.
- Середні — фрагменти штрихів, дуги, перетини.
- Верхні — цілий гліф, схожий на клас.
Схема: зображення → згортки → пулінг → ознаки → повнозв’язний шар → 10 класів.
Чому CNN — хороший baseline
| Критерій | CNN |
|---|---|
| Розмір моделі | Десятки–сотні КБ – кілька МБ |
| Час навчання | Хвилини–години на GPU, години на CPU |
| Inference | Мілісекунди на комірку |
| Відладка | Confusion matrix, візуалізація помилок |
| Деплой | Легко упакувати в ONNX, TFLite, edge |
На першому експерименті виміряйте не лише accuracy, а й confusion matrix, час inference, розмір артефакта. Ці цифри стануть аргументом проти «давайте одразу TrOCR» на нараді.
Мінімальний експеримент
# Псевдокод: класифікатор 10 класів
model = Sequential([
Conv2D(32, 3, activation='relu'),
MaxPooling2D(),
Conv2D(64, 3, activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(128, activation='relu'),
Dense(10, activation='softmax'),
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
Для production додайте нормалізацію розміру комірки, інверсію при темному фоні та логування впевненості (softmax probability).
Кілька цифр в одній комірці
Комірка [ 78 ] ламає постановку «один клас на картинку». Наївний шлях:
78 → сегментація → 7 | 8 → два прогони CNN → "78"
Чому сегментація — окрема проблема
- Цифри різного розміру в одній комірці.
- Відстань між символами непостійна.
- Символи торкаються або перекриваються.
- Лінії таблиці проходять крізь штрихи.
- Почерк не дотримується моноширинної сітки.
Кожен із цих факторів додає етап, який сам по собі потребує розмітки й метрик. Простіше запитати: чи можна розпізнати всю послідовність одразу? Тут з’являється CTC.
CTC: послідовність без посимвольної розмітки
Connectionist Temporal Classification вчить відповідність між зображенням і рядком без розмітки меж кожного символу. Достатньо пари ціла комірка → "783".
Інтуїція
Модель на кожному часовому кроці видає розподіл за символами плюс спеціальний токен blank (порожній крок). Декодер CTC згортає повтори й прибирає blank:
сирій вихід: 7 → 7 → blank → 8 → 8 → 8 → blank → 3
після CTC: 7 → 8 → 3
Вам не потрібно вручну малювати bounding box навколо кожної цифри.
Обмеження CTC
- Послідовність зазвичай моделюється зліва направо (для цифр у комірці це частіше за все ок).
- Двовимірна структура тексту CTC переносить гірше, ніж seq2seq з attention.
- Довжина вхідної послідовності ознак повинна бути порівнянна з довжиною рядка — для коротких чисел у комірці обмеження рідко заважає.
CRNN — класичний робочий кін OCR
Convolutional Recurrent Neural Network об’єднує згортки, рекурентні шари й CTC:
image → CNN → feature map → sequence → BiLSTM → CTC → "783"
Навіщо RNN між CNN і CTC
Текст має порядок: 7 потім 8 потім 3. Feature map після CNN можна розрізати на смуги зліва направо; кожна смуга — крок часу. BiLSTM дивиться в обидва боки й уточнює, який символ ймовірний з урахуванням сусідів.
Плюси й мінуси
| Плюси | Мінуси |
|---|---|
| Компактна модель | RNN повільніший за паралельні Transformer на довгих послідовностях |
| Добре вивчений, багато рецептів | Складніше тюнити, ніж простий CNN |
| Працює на CPU для коротких рядків | Гірше масштабується на вільний текст |
| Пряме навчання end-to-end з CTC | Менш гнучкий при зміні алфавіту, ніж generative decoder |
Для комірок із двома–п’ятьма цифрами CRNN + CTC залишається сильним вибором у 2026 році — особливо якщо важливі розмір моделі й inference на CPU.
TrOCR — коли в гру входить Transformer
TrOCR (Transformer-based OCR) — end-to-end модель: Vision Transformer кодує зображення, Transformer decoder генерує текст посимвольно.
image → ViT encoder → visual tokens → text decoder → "783"
CRNN проти TrOCR
| CRNN + CTC | TrOCR | |
|---|---|---|
| Енкодер | CNN | Vision Transformer |
| Декодер | CTC (вирівнювання) | Autoregressive Transformer |
| Попереднє навчання | Зазвичай з нуля на своїх даних | Доступні ваги на друкованому/рукописному тексті |
| Розмір | Малий–середній | Small / Base / Large |
| Сильна сторона | Короткі цифрові рядки | Складний текст, змішаний алфавіт |
Fine-tuning pretrained
Типовий рецепт: взяти microsoft/trocr-base-handwritten або аналог, дообучити на своїх комірках з цифрами. Pretrained знання про штрихи й криві переносяться; останні шари адаптуються до вашого домену — ліній таблиці, шуму камери, локального почерку.
Важливо: більше параметрів ≠ краще на вашій вибірці. Large-модель може переобучитися на тисячі комірок, тоді як Small дасть ту саму CER при inference у десять разів швидше.
Чому TrOCR може бути надлишковим
Головний тезис: якщо задача формулюється як image → "7" у відомій комірці з алфавітом із десяти цифр, повноцінний OCR-Transformer — стрілянина з гармати по горобцях.
TrOCR стає цікавішим, коли:
- у комірці змінна довжина (
7835,12,0); - алфавіт розширюється (літери, десяткова крапка, знак мінус);
- якість зйомки сильно варіює і pretrained дає помітний перенос;
- планується єдина модель на цифри й короткий текст у сусідніх полях.
Якщо ж:
- шаблон фіксований;
- алфавіт — лише
0–9; - довжина обмежена (наприклад, не більше п’яти символів);
- область тексту вирізана геометрією,
то спеціалізована CRNN або навіть каскад CNN часто виграє за latency, вартістю й простотою супроводу.
Експеримент: CNN vs CRNN vs TrOCR на одному датасеті
Порівняння архітектур має сенс лише на однакових даних і з чесним сплітом.
Розбиття вибірки
Типове співвідношення: 70% train, 15% validation, 15% test — але всередині груп:
- за
document_id(усі комірки одного бланка — в одному спліті); - за
author_id/ оператором; - за серією бланків або датою зйомки.
Випадкове перемішування комірок без групування завищує метрики.
Метрики
Для однієї цифри (CNN):
- Accuracy;
- Precision / Recall за класами;
- Confusion matrix.
Для послідовності (CRNN, TrOCR):
- CER (Character Error Rate);
- Exact Match Accuracy;
- Sequence Accuracy.
Інженерні метрики (часто вирішують спір на проді):
| Метрика | Навіщо |
|---|---|
| Розмір моделі | Деплой на edge, мобільний додаток |
| Час inference на CPU/GPU | Пропускна здатність на зміну |
| VRAM / RAM | Батч на сервері |
| Throughput | Комірок на секунду на лінії |
| Час навчання | Як швидко переобучити після зміни бланка |
Зафіксуйте залізо й batch size в звіті — інакше порівняння безглузде.
Аналіз помилок важливіший за одну цифру accuracy
accuracy = 98.7% звучить добре, доки не відкриєте confusion matrix. Типові пари плутанини на рукописних цифрах:
1 ↔ 73 ↔ 85 ↔ 60 ↔ 64 ↔ 9
Що дивитися крім матриці
- Почерк: які оператори чи контрагенти дають гірший CER;
- Інструмент письма: гелева ручка vs олівець;
- Освітлення: відблиск на ламінованому бланку;
- Розмір цифр: дрібний почерк у вузькій комірці;
- Артефакти зйомки: змаз, обрізаний край комірки.
Зберіть папку hard examples — 50–200 комірок, де всі моделі помиляються. Дообучення на hard set або ручна перевірка цих кейсів часто дає більше, ніж зміна Large на Base.
Цикл покращення:
звичайні приклади → помилки на val → hard examples →
аугментація / дообучення / правила → повтор
Спостережуваність такого конвеєра — логування впевненості, збереження кропів з низьким score, дашборд CER за полем і оператором — перетинається з практиками з AI observability.
Data augmentation: імітація камери, не фантазія
Аугментація допомагає при нестачі даних, якщо вона імітує реальні умови зйомки:
- невеликий поворот і зсув;
- масштаб;
- зміна контрасту й яскравості;
- гаусів шум;
- легке розмиття;
- невелика перспективна деформація;
- випадкова обрізка зі збереженням цифри в кадрі.
Погана аугментація — та, якої немає в production: екстремальні спотворення, інверсія кольору без сенсу, накладання випадкових ліній не там, де бувають лінії таблиці.
Якщо лінії таблиці — головне джерело помилок, краще прибрати їх на етапі попередньої обробки (морфологія, кольорова маска, inpainting ліній), ніж сподіватися, що модель «звикне».
Semi-supervised learning і human-in-the-loop
Коли baseline уже працює, можна замкнути цикл:
впевнене розпізнавання → pseudo-label → нові training samples → переобучення
Confidence threshold
Якщо confidence > threshold (наприклад, 0.95 для CNN або низький CER beam search для CRNN), приклад додається в пул із псевдорозміткою. Нижче порогу — в чергу людині.
Human-in-the-loop
model → confidence → high: accept / low: human review → БД
Це знижує вартість розмітки й не дає моделі тихо деградувати: частка ручних перевірок — метрика здоров’я системи.
Обережно з feedback loop: якщо модель систематично плутає 5 і 6, псевдорозмітка посилить помилку. Періодично підмішуйте верифіковані людиною приклади й моніторьте confusion matrix на свіжому потоці.
Production pipeline: більше, ніж нейромережа
Підсумковий ланцюжок для структурованого бланка:
photograph → document detection → perspective correction →
template alignment → cell extraction → preprocessing →
OCR model → confidence → validation rules → database
Де працюють детерміновані правила
Нейромережа не повинна вирішувати те, що задано бізнес-логікою:
- поле допускає лише цифри;
- значення в діапазоні
0–100; - фіксована кількість знаків (наприклад, показання лічильника — рівно п’ять цифр);
- контрольна сума або повторне читання сусіднього поля.
Якщо OCR повернув 783 для поля з максимумом 100, правило відхиляє результат незалежно від softmax.
Каскад моделей
Не обов’язково обирати одну архітектуру:
швидкий CNN → впевнений? → accept
↓ ні
CRNN або TrOCR → впевнений? → accept
↓ ні
human review
Чому це часто краще за одну велику модель:
- дешевше в середньому на комірку;
- швидше на «легких» прикладах;
- простіше масштабувати навантаження;
- складні випадки отримують більше обчислень, а не всі підряд.
Що обрати для реальної системи
| Задача | Рекомендація |
|---|---|
| Одна цифра в комірці | CNN |
| Кілька цифр, свій датасет | CRNN + CTC |
| Змішаний текст, розширення алфавіту | TrOCR fine-tune |
| Фіксований бланк | Geometry + вузька модель на комірку |
Архітектурна карта:
ОДНА ЦИФРА → CNN
КІЛЬКА ЦИФР → CRNN + CTC
СКЛАДНИЙ ТЕКСТ → TrOCR
СТРУКТУРОВАНИЙ → Document AI + geometry + OCR на комірках
ДОКУМЕНТ
Що ця задача каже про вибір нейромереж
Не починайте з питання «яка зараз найпотужніша модель?». Починайте з «яка структура моєї задачі?»
- 10 класів, одна цифра — не потрібен generative OCR.
- Послідовність символів без посимвольних box — CTC / CRNN.
- Складний текст і перенос pretrained — Transformer-моделі на кшталт TrOCR.
- Відомий шаблон — Document AI на рівні геометрії знімає половину ML-складності.
Архітектура повинна слідувати структурі інформації, а не популярності моделі в стрічці.
Що зробити сьогодні
- Зафіксуйте постановку: одна цифра чи рядок? Яка максимальна довжина?
- Намалюйте пайплайн до ML: вирівнювання бланка й нарізка комірок у пріоритеті.
- Перевірте джерело розмітки: чи можна пов’язати фото з БД?
- Навчіть CNN baseline і збережіть confusion matrix.
- Якщо в комірці кілька цифр — CRNN + CTC на тих самих кропах.
- Порівняйте з TrOCR Small лише після чесного спліту за документами.
- Введіть поріг впевненості і чергу ручної перевірки до «повного автомата».
Подальше читання
FAQ
Чи можна почати з готового Tesseract?
Так, як з дуже грубого baseline на вирізаних комірках. Tesseract розрахований на рядки тексту; на окремих рукописних цифрах у комірці з лініями сітки часто програє маленькій CNN. Має сенс для швидкої перевірки «чи є сигнал у даних», але рідко як фінальне рішення для польових бланків.
Скільки даних потрібно для CNN?
Порядок величини: від кількох сотень прикладів на клас для простого домену до кількох тисяч, якщо почерк сильно різнорідний. Без аугментації й без групового val/test цифри будуть оманливими.
Чи працює CTC для порожньої комірки?
Потрібен явний клас «порожньо» або окремий детектор порожнечі до OCR. Інакше модель буде «галюцинувати» цифри на шумі й лініях таблиці.
TrOCR Base чи Small для тисячі комірок?
Почніть зі Small: швидші ітерації, менший ризик переобучення. Base має сенс, якщо Small упирається в CER на validation, а не на train.
Як пов’язати OCR з ERP?
Після валідації поля пишіть в API ERP або в проміжну чергу з ідемпотентним ключем document_id + field_id. Патерни інтеграції — у ERP integration.
Чи потрібен GPU в production?
Для CNN на одній комірці — часто ні, CPU вистачає. Для батча TrOCR на сервері — бажано. Каскад «CNN на CPU → TrOCR на GPU для складних» — типовий компроміс.
Як не змішати train і test одного бланка?
Зберігайте document_id в метаданих кожного кропа й використовуйте GroupKFold або явний спліт за списком документів. Будь-який випадковий train_test_split без груп — червоний прапорець.
Що робити, якщо accuracy висока, а користувачі скаржаться?
Дивіться помилки на репрезентативному тесті (нові люди, нові умови зйомки), а не на випадкових кропах. Висока accuracy на «легкому» тесті при поганому досвіді в полі — класичний симптом leakage або зміщеної вибірки.

