Как добавить распознавание паспорта в мобильное приложение iOS и Android за 5 минут: 4 шага

Автоматическое распознавание паспорта РФ в мобильном приложении – ключевой элемент удаленной идентификации пользователя в 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 поставляется в виде трех частей:

  1. Нативная сборка библиотеки под платформу;
  2. Конфигурационный бандл с данными о поддерживаемых документах;
  3. Обертка для вызова функций библиотеки из кода приложения.

Преимущества распознавания паспорта в мобильном приложении

Мобильное клиентское распознавание – то есть выполнение всей обработки прямо на устройстве пользователя, без обращения к серверу, – дает компаниям ряд практических преимуществ.

  • Автономная работа без подключения к интернету;
  • Максимальная производительность библиотеки;
  • Лучший пользовательский опыт при распознавании в видеопотоке, двустороннем распознавании документов, небиометрической сверке лиц и проверке живости;
  • изображение документа и извлеченные из него данные не покидают устройство пользователя – это исключает передачу персональных данных и другой конфиденциальной информации на внешние серверы и в облачные сервисы.

Эти и другие преимущества распознавания в мобильном приложении позволяют добиться наилучшего пользовательского опыта при онбординге, обеспечив высокий уровень безопасности обработки конфиденциальной информации.

По сравнению с отправкой данных в облачный сервис распознавание 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

  1. Затем в build.gradle (module) подключается обертка:
    dependencies { implementation(fileTree("libs") { include("*.jar") }) }

  2. Также необходимо подключить в 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 в свой проект, нужно:

  1. перетащить папку SESmartID с кодом обёртки из SDK в проект, при добавлении выбрать Create Groups;
  2. сделать то же самое для папки lib с xcframewok
  3. перетащить папку data-zip с конфигурацией, при добавлении выбрать Create Folder References;
  4. добавить папку 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.

Содержание