Користувач наводить камеру на розмитий чек у напівтемряві. Без попередньої обробки знімка стандартні OCR-бібліотеки видають до 50% помилок. Рішення — на етапі захвату застосувати підвищення контрастності (vImageContrastStretch на iOS, OpenCV на Android) та бінаризацію. Тільки після цього подавати кадр у VNRecognizeTextRequest або ML Kit Text Recognition. У нашій практиці такий ланцюг підвищує точність з 70% до 98-99% на друкованому тексті.
За 5 років ми реалізували понад 20 проєктів OCR для рітейлу (розпізнавання цінників і чеків), логістики (трекінг накладних) та фінтеху (верифікація паспортних даних). У кожному проєкті — свій набір фільтрів і постобробки. Типова помилка — вважати, що OCR-бібліотека видасть ідеальний результат «з коробки». Без попередньої обробки зображення та постобробки результату точність падає до 50–70%. Тому перший етап будь-якого проєкту — збір реальних зразків документів і тестування на них.
Чому попередня обробка критична для точного OCR?
Попередня обробка — ключовий етап, що визначає підсумкову точність. У поганому освітленні або при розмитті ми використовуємо:
- Підвищення контрастності через
vImageContrastStretch(iOS) абоOpenCV(Android). - Переведення в grayscale з наступним
AdaptiveThreshold. -
SharpenCIFilter перед подачею в OCR.
Для рукописного тексту стандартні фреймворки показують точність 40–60%. У таких випадках допомагають кастомні моделі на базі TensorFlow Lite — це окреме завдання, що потребує розмічених даних і навчання. Джерело: документація TensorFlow Lite
Як працюють нативні OCR-фреймворки?
iOS: Vision + VNRecognizeTextRequest — ocr в мобільному
Починаючи з iOS 13 Vision фреймворк вміє розпізнавати текст без інтернету. VNRecognizeTextRequest підтримує два режими: .fast (приблизно, миттєво) та .accurate (повільніше, але значно точніше для складних шрифтів). Для складних шрифтів режим .accurate дає приріст точності на 15%.
func recognizeText(in image: UIImage) {
guard let cgImage = image.cgImage else { return }
let request = VNRecognizeTextRequest { [weak self] request, error in
guard let observations = request.results as? [VNRecognizedTextObservation] else { return }
let text = observations.compactMap { $0.topCandidates(1).first?.string }.joined(separator: "\n")
DispatchQueue.main.async { self?.handleRecognized(text: text) }
}
request.recognitionLevel = .accurate
request.usesLanguageCorrection = true
request.recognitionLanguages = ["ru-RU", "en-US"] // порядок = пріоритет
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try? handler.perform([request])
}
usesLanguageCorrection допомагає з опечатками, але іноді «виправляє» абревіатури та артикули — для технічних документів краще вимкнути.
Android: ML Kit Text Recognition v2
com.google.mlkit:text-recognition підтримує латиницю, кирилицю, китайську, японську, корейську через окремі модулі. Завантажується на пристрій при першому використанні (~5 MB для латиниці).
val recognizer = TextRecognition.getClient(
TextRecognizerOptions.DEFAULT_OPTIONS // або RussianTextRecognizerOptions
)
val image = InputImage.fromBitmap(bitmap, 0)
recognizer.process(image)
.addOnSuccessListener { visionText ->
val fullText = visionText.textBlocks
.joinToString("\n") { block -> block.text }
handleRecognized(fullText)
}
.addOnFailureListener { e -> handleError(e) }
ML Kit також повертає bounding boxes для кожного блоку тексту — корисно для підсвічування розпізнаних областей в UI.
Live-режим: текст у реальному часі з відеопотоку
Для live-overlay (текст підсвічується прямо у відеопотоці) на iOS використовуємо AVCaptureSession + CMSampleBuffer:
// Delegate метод AVCaptureVideoDataOutput
func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
// Не запускаємо новий запит, якщо попередній ще не завершився
guard !isProcessing else { return }
isProcessing = true
let request = VNRecognizeTextRequest { [weak self] request, _ in
defer { self?.isProcessing = false }
// обробка результатів...
}
request.recognitionLevel = .fast // для live важлива швидкість
try? VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]).perform([request])
}
Прапор isProcessing обов’язковий — без нього при 30 FPS накопичується черга запитів і пам’ять зростає до крашу.
На Android — CameraX + ImageAnalysis.Analyzer. ML Kit оптимізований для роботи з ImageProxy напряму без конвертації в Bitmap.
| Параметр | Статичне розпізнавання | Live-розпізнавання |
|---|---|---|
| Швидкість обробки | 100-200 мс | до 30 мс на кадр |
| Точність | до 99% | до 95% (через компроміс швидкості) |
| Споживання батареї | низьке | середнє (постійна обробка) |
| Застосування | сканування документів, чеків | наведення на візитки, номерні знаки |
Як покращити якість розпізнавання у складних умовах?
Підвищення контрастності та бінаризація — стандартні прийоми. Для специфічних документів (наприклад, чеків з вицвілим друком) ми підключаємо кастомні фільтри. Економія від автоматизації введення даних за допомогою OCR може досягати 200 000 гривень на рік на один відділ — це в 3 рази більше порівняно з ручним введенням.
Типові помилки при інтеграції OCR:
- Забувають прапор isProcessing в live-режимі → витік пам’яті.
- Залишають usesLanguageCorrection увімкненим для технічних текстів → псує абревіатури.
- Не перевіряють bounding boxes на перетин з UI → текст накладається на інтерфейс.
Постобробка: від «сирого» тексту до структурованих даних
Голий OCR-результат — це потік рядків. Для більшості завдань потрібна структуризація:
- Чеки: виділяємо рядки з цінами за regex, парсимо підсумкову суму
- Візитки:
NSDataDetector(iOS) абоPatterns(Android) для телефонів, email, адрес - Паспорти/документи: MRZ-зона читається за стандартом ICAO 9303, є готові парсери
- Номерні знаки: окреме завдання — краще спеціалізована модель (OpenALPR, PlateRecognizer API)
Для кириличного тексту з поганою якістю іноді допомагає попередня обробка зображення: збільшення контрастності через vImageContrastStretch, переведення в grayscale, Sharpen CIFilter перед передачею в OCR.
Порівняння нативних фреймворків
| Параметр | Vision (iOS) | ML Kit (Android) |
|---|---|---|
| Режими | .fast, .accurate | базова модель |
| Мови | до 15 в одному запиті | модулі: лат, кир, кит, яп, кор |
| Офлайн | так | так (модель ~5 MB) |
| Точність на друкованому | ~98% | ~97% |
| Bounding boxes | так | так |
| Швидкість (full HD) | 100-200 мс | 80-150 мс |
Що входить у розробку OCR-функції
При замовленні цієї послуги ви отримуєте:
- Інтеграцію Vision або ML Kit у ваш додаток.
- Налаштування параметрів розпізнавання під ваш тип документів.
- Live-режим з виведенням підсвічування тексту на камері (опціонально).
- Постобробку даних: парсинг чеків, візиток, номерів.
- Документацію з інтеграції та тестування.
- Підтримку при проходженні ревʼю App Store / Google Play.
- Гарантію на працездатність рішення протягом 6 місяців.
Процес роботи
- Визначення сценаріїв використання: тип документів, мови, чи потрібен live-режим або тільки статичне фото.
- Реалізація захвату зображення (camera + галерея), попередня обробка.
- Інтеграція OCR: нативний Vision/ML Kit або хмарний (Google Vision API, AWS Textract) якщо потрібна вища точність для складних документів.
- Постобробка під конкретне завдання: структурування даних, regex, NER.
- Тестування на реальних зразках у різних умовах освітлення.
Орієнтири за термінами
Базове розпізнавання статичного тексту через нативний фреймворк — 2–3 дні. Live-режим з overlay + структурування даних під конкретний тип документа — 1–2 тижні. Складні сценарії з кастомними моделями — від місяця. Вартість визначається після аналізу вашого проєкту.
Отримайте консультацію щодо вашого проєкту — ми підберемо оптимальне рішення. Зв’яжіться з нами, щоб обговорити задачу та розрахувати вартість розробки OCR для вашого додатку.
Часто задавані питання
Яку точність OCR можна очікувати в мобільному додатку? Точність залежить від умов: на чітких друкованих текстах з хорошим освітленням — до 99%. Для рукописного тексту або сильно спотворених зображень точність падає до 70-80%. Використання попередньої обробки зображення та кастомних моделей може підвищити точність на 10-15%.
Чи працює OCR без інтернету? Так, нативні фреймворки Vision (iOS) та ML Kit (Android) повністю працюють офлайн. Моделі завантажуються на пристрій при першому запуску. Для складніших завдань (наприклад, розпізнавання паспортних даних) може знадобитися хмарний API для підвищення точності.
Які мови підтримують ML Kit та Vision? Vision підтримує латиницю, кирилицю, китайську, японську, корейську та інші. ML Kit має окремі модулі: латиниця, кирилиця, китайська, японська, корейська. Для розпізнавання кількох мов в одному кадрі потрібно вказати всі мови в порядку пріоритету.
Скільки часу займає розробка OCR-функції? Базова інтеграція статичного розпізнавання займає 2–3 дні. Live-режим з виведенням тексту поверх камери та структуруванням даних під конкретний тип документа — від 1 до 2 тижнів. Складні сценарії (наприклад, розпізнавання чеків з наступним парсингом) можуть зайняти до місяця.
Чи можна використовувати OCR для розпізнавання номерів автомобілів? Для номерних знаків краще використовувати спеціалізовані рішення, такі як OpenALPR або PlateRecognizer API. Стандартні OCR-фреймворки не оптимізовані під цей сценарій і показують низьку точність через особливості шрифтів та кутів зйомки.







