Автоматическое распознавание паспорта РФ в мобильном приложении – ключевой элемент удаленной идентификации пользователя в 2026 году. С помощью этой технологии можно реализовать процедуры цифрового онбординга, KYC, AML, возрастной идентификации и другие востребованные бизнес-сценарии, в которых требуется подтвердить личность клиента по документу.
Ниже приведена пошаговая инструкция по интеграции SDK Smart Engines для распознавания паспорта в мобильные приложения на iOS и Android.
Mobile OCR SDK
SDK Smart ID Engine – это проприетарная библиотека для распознавания удостоверяющих личность документов, написанная на C++ и не привязанная к конкретной ОС или архитектуре. Сборка SDK возможна под семейства операционных систем: RHEL, Debian, Alpine, Windows, macOS, Android, iOS и WebAssembly, а также под российские ОС – Astra, РЕД ОС, РОСА «Хром», Axiom Linux.
Алгоритмы оптимизированы под все основные аппаратные архитектуры, включая ARM (ARMv7-v8, AArch64) и x86/x86_64, поэтому библиотека без изменения бизнес-логики переносится с одной платформы на другую. C++-интерфейс библиотеки оборачивается под конкретный язык программирования – для мобильной разработки это Java (Android) и Objective-C/Swift (iOS), также доступны обертки под C#, Python3 и PHP7/8.
Для интеграции в мобильное приложение SDK поставляется в виде трех частей:
- Нативная сборка библиотеки под платформу;
- Конфигурационный бандл с данными о поддерживаемых документах;
- Обертка для вызова функций библиотеки из кода приложения.
Преимущества распознавания паспорта в мобильном приложении
Мобильное клиентское распознавание – то есть выполнение всей обработки прямо на устройстве пользователя, без обращения к серверу, – дает компаниям ряд практических преимуществ.
- Автономная работа без подключения к интернету;
- Максимальная производительность библиотеки;
- Лучший пользовательский опыт при распознавании в видеопотоке, двустороннем распознавании документов, небиометрической сверке лиц и проверке живости;
- изображение документа и извлеченные из него данные не покидают устройство пользователя – это исключает передачу персональных данных и другой конфиденциальной информации на внешние серверы и в облачные сервисы.
Эти и другие преимущества распознавания в мобильном приложении позволяют добиться наилучшего пользовательского опыта при онбординге, обеспечив высокий уровень безопасности обработки конфиденциальной информации.
По сравнению с отправкой данных в облачный сервис распознавание on-device также предлагает более быстрый отклик, полностью безопасную обработку без раскрытия конфиденциальной информации третьим лицам и рисков утечки, а также соответствие законодательным нормам в области обработки персональных данных.
| Обработка в облаке | Распознавание на устройстве | |
| Скорость распознавания | ⚠️ Зависит от качества интернет-соединения | ✅ Мгновенно |
| Качество распознавания | ⚠️ Зависит от качества OCR | ✅ До 100% |
| Отправка на внешний сервер | ⚠️ Обязательна | ✅ Не требуется |
| Работа оффлайн | ❌ Невозможно | ✅ Да |
| Риски при обработке | ❌ Риск утечки | ✅ Исключены |
Базовые понятия библиотеки распознавания
- Движок распознавания: создается один раз при старте приложения с указанием конфигурационного бандла и функционирует все время. От него создаются следующие элементы интерфейса:
- Сессия распознавания: процесс распознавания конкретного документа (паспорта РФ, ВУ, СТС и других – всего библиотека поддерживает более 3000 типов). В сессию можно передать одно изображение или серию кадров из видеопотока: с каждым новым кадром результат уточняется; система автоматически определяет оптимальный момент остановки сессии распознавания.
- Настройки сессии: хранят список доступных для распознавания типов документов (определяется конфигурационным бандлом), дополнительную информацию о каждом документе, а также позволяют настроить процесс распознавания: задать список ожидаемых типов документов для сессии распознавания, включить\выключить проверки признаков подлинности, задать таймаут для сессии распознавания и пр. Настройки создаются перед созданием самой сессии и не могут редактироваться в процессе распознавания.
- Результат распознавания: объект со структурированными текстовыми полями, изображениями (например, фото владельца), координатами документа на кадре и данными проверок подлинности.
Общая логика работы одинакова для любой платформы и любого продукта линейки Smart Engines: движок → настройки сессии → сессия → разбор результата. Ниже – как эта схема выглядит в коде на Android и на iOS.
Все обращения к API предполагают работу через JNI-интерфейс, что несет определенные ограничения. Например, невозможно передавать ссылки на JNI-структуры между потоками.
Пошаговое встраивание в Android-приложение
-
- Папка с библиотеками jniLibs/ в вашу папку app/src/main/jniLibs/
- Файл обертки jni*.jar — в папку app/src/main/libs/
- Бандл — набор документов для распознавания — в папку app/src/main/assets/data/*.se
Затем в build.gradle (module) подключается обертка:dependencies { implementation(fileTree("libs") { include("*.jar") }) }
Также необходимо подключить в Proguard rules-keep class com.smartengines.common.* { public ; } -keep class com.smartengines.id.* { public ; }
1. Создание движка распознавания
Библиотеку можно инициализировать в любой момент, но если ее использование планируется довольно часто, можно делать это при старте Application.onCreate()
Перед вызовом любых функций, необходимо загрузить нативную JNI-библиотеку в JVM.
System.loadLibrary("jniidengine")
Теперь читаем файл конфигурации в память:
// Open an input stream
val stream: InputStream = context.assets.open("your_bundle_filename", AssetManager.ACCESS_STREAMING)
// Read data from the stream
val size = stream.available()
val data = ByteArray(size)
val result = stream.read(data)
stream.close() if (result != size) throw Exception("stream reading error")
Создание инстанса движка:
// engine init
val engine = IdEngine.Create(data,
true, // lazyConfiguration
0, // initConcurrency
true // delayedInitialization
2. Настройка сессии распознавания
Библиотеке необходимо сообщить, какие документы и в каком режиме распознавать:
// Create session settings
val sessionSettings = engine.CreateSessionSettings()
// Fill the session setting according to the target
with(sessionSettings){
// Common
SetOption("common.sessionTimeout", "5.0")
// ID session settings
SetCurrentMode(mode)
AddEnabledDocumentTypes(mask)
}
// Create Session
val session = engine.SpawnSession( sessionSettings, signature )
Режим и маска документа позволяют искать группы документов, когда точно неизвестно, какой документ будет расположен перед камерой.
Настройки сессии позволяют регулировать процесс распознавания.
Например, опция таймаута обязывает систему вернуть результат через 5 секунд, даже если система так и не была в нем уверена.
3. Создание Image и распознавание
Перед распознаванием необходимо создать изображение класса se.common.Image независимо от его источника. Для каждого формата есть примеры реализации.
Само распознавание выглядит так:
val result = session.Process(image)
Если вы работаете с видеопотоком – обрабатывайте кадры последовательно в рамках одной и той же сессии. Это позволяет существенно улучшать качество результата.
Система самостоятельно принимает решение о том, что кадров достаточно. Этот механизм называется терминальностью.
Терминальность – автоматическая остановка процесса распознавания в видеопотоке. Принимает значение true в двух случаях:
- добавление новых кадров не приведет к изменению результата распознавания;
- исчерпалось ограничение времени сессии, заданное в настройках.
Таким образом вы всегда получаете ответ от системы.
fun processVideoFrame(image: Image) {
val result = session.Process(image)
if ( result.GetIsTerminal() ) // stop the process
}
4. Разбор результатов распознавания
Результат распознавания хранит в себе множество информации. Помимо собственно текстовых полей и фото владельца, результат содержит координаты документа на изображении, сами изображения документа, обрезанные по шаблону, данные проверок признаков подлинности и иные атрибуты.
Пример итератора для разбора текстовых полей:
val iterator = result.TextFieldsBegin()
val end = result.TextFieldsEnd()
while (!iterator.Equals(end)) {
// Load the field data
val textFiaeld : IdTextField = iterator.GetValue()
with(textField){
val info = GetBaseFieldInfo()
val key = GetName(), //the same as iterator.GetKey(),
val value = GetValue().GetFirstString().GetCStr(),
val isAccepted = info.GetIsAccepted(),
val attr = info.parseAttributes()
}
// Next field
iterator.Advance()
}
Полный код доступен на GitHub.
Освобождение памяти
JVM не управляет памятью в C++. Сборщик мусора не имеет доступа к объектам, которые порождает С++.
Большинство классов библиотеки Smart Engines содержат фабричные методы, возвращающие указатели на объекты, поэтому ответственность за освобождение памяти лежит на том, кто пользуется этим объектом. Впрочем, в примерах Smart Engines уже реализован этот подход.
Обязательно освобождайте ресурсы, как перестаете в них нуждаться. session.Reset(), image.delete(), engine.delete()
Пошаговое встраивание в iOS-приложение
В отличие от android на iOS логика взаимодействия с C++ движком инкапсулирована в готовую Objective-C обертку SESmartID.
Демо-версия SDK для iOS выложена в открытый доступ на GitHub – на ее примере ниже показано, как подключить распознавание паспорта к своему приложению.
Чтобы добавить SDK в свой проект, нужно:
- перетащить папку
SESmartIDс кодом обёртки из SDK в проект, при добавлении выбрать Create Groups; - сделать то же самое для папки
libс xcframewok - перетащить папку
data-zipс конфигурацией, при добавлении выбрать Create Folder References; - добавить папку
includeв Header Search Paths проекта.
SESmartID — код Objective-C GUI-обёртки над C++ ядром, с которой и происходит взаимодействие;
SESmartIDCore — конфигурационный бандл, C++ заголовочные файлы, xcframework.
1. Создание контроллера распознавания
Основной класс обертки, с которым происходит взаимодействие, называется SESIDViewController.
Чтобы получать результаты распознавания, нужно добавить в свой класс протокол SESIDViewControllerDelegate и сам объект обёртки:
#import "SESIDViewController.h"
@interface SESIDSampleViewController : UIViewController <SESIDViewControllerDelegate>
@property (nonatomic, strong) SESIDViewController *smartIdViewController;
@end
2. Конфигурация ядра распознавания
- (void) initializeSmartIdViewController {
// Создаем ядро/экран распознавания
self.smartIdViewController = [[SESIDViewController alloc] init];
// Проставляем делегат, через который к нам придет результат распознавания
self.smartIdViewController.delegate = self;
}
3. Показ экрана распознавания
Когда нужно отсканировать документ, показываем экран распознавания, указав, какие типы документов ожидаются в рамках текущей сессии:
- (void) showSmartIdViewController {
// Указываем, какие документы требуется распознавать
// Документация содержит подробное описание возможных типов документов и т.п.
[self.smartIdViewController addEnabledDocumentTypesMask:"rus.passport.*"];
// [self.smartIdViewController addEnabledDocumentTypesMask:"mrz.*"];
// [self.smartIdViewController addEnabledDocumentTypesMask:"card.*"];
// Можно контролировать таймаут в секундах, после которого распознавание закончится
self.smartIdViewController.sessionTimeout = 5.0f;
// Показываем экран распознавания
[self presentViewController:self.smartIdViewController
animated:YES
completion:nil];
}
4. Разбор результатов распознавания
Во время сканирования вызываются два делегатных метода, которые нужно реализовать, чтобы получить результат:
// Вызывается после распознавания очередного кадра видеопотока
- (void) smartIdViewControllerDidRecognizeResult:(const se::smartid::RecognitionResult &)result {
// Флаг "терминальности" проставляется, когда движок полностью уверен в результате или когда истек таймаут
if (!result.IsTerminal()) {
// Здесь можно показать промежуточный результат на экране или ничего не делать
return;
}
// Закрываем экран распознавания
[self dismissViewControllerAnimated:YES completion:nil];
// Используем результат распознавания
// Можно получить названия всех присутствующих строковых полей
const std::vector<std::string> &stringFieldNames = result.GetStringFieldNames();
// Или взять интересующее строковое поле
const se::smartid::StringField &field = result.GetStringField("second_name");
// Проверить, уверен ли движок в результате
const BOOL fieldAccepted = field.IsAccepted();
// И взять его содержимое
NSString *fieldValue = [NSString stringWithUTF8String:field.GetUtf8Value().c_str()];
// То же самое можно сделать для изображений: фотографии и других
if (result.HasImageField("photo")) {
const se::smartid::Image &image = result.GetImageField("photo").GetValue();
self.resultImageView.image = [SESIDViewController uiImageFromSmartIdImage:image];
}
}
// Вызывается при отмене сканирования пользователем
- (void) smartIdViewControllerDidCancel {
// Закрываем экран распознавания
[self dismissViewControllerAnimated:YES completion:nil];
}
Набор шагов для iOS зеркалит логику Android-интеграции: создать ядро, задать настройки сессии (в данном случае – маску типов документов и таймаут), показать экран распознавания и разобрать результат в делегате. Помимо ручного добавления папок в проект, SDK также поддерживает подключение через SPM (Swift Package Manager) и CocoaPods.
Что еще можно сделать с помощью SDK
Распознавание документа на камеру – лишь один из сценариев использования Smart ID Engine. По той же схеме «движок → настройки сессии → сессия → разбор результата» в мобильное приложение можно добавить:
- небиометрическую сверку лиц – сравнение двух изображений на степень схожести;
- проверку живости лица (liveness) – без выявления биометрических дескрипторов;
- двустороннее распознавание документов – когда нужно считать данные с обеих сторон паспорта, ВУ или другого удостоверения;
- распознавание в видеопотоке – система анализирует поступающие кадры до тех пор, пока не наберёт достаточно данных, поэтому пользователю не приходится переснимать смазанный или засвеченный кадр вручную.
Та же логика встраивания применима и к другим продуктам линейки Smart Engines.
Мобильное клиентское распознавание — не единственный вариант интеграции Smart ID Engine. Та же библиотека может работать и на сервере, как часть десктоп-приложения (например, для работы с планшетными сканерами и веб-камерами) или как WebAssembly-модуль в браузере или мессенджеры. Выбор конкретного варианта зависит от того, какие документы нужно распознавать и откуда поступает изображение – подробнее об этом можно прочитать на сайте Smart Engines.