Специальная программа для малого и среднего бизнеса

Интеграция Smart Engines SDK в Android

Минимальный пример интеграции в Android-приложение на Kotlin.

Состав SDK:

  • doc — документация
  • Sample/ — семпл
  • Sample/app/src/main/jniLibs/ — универсальная статическая библиотека для android устройств и эмулятора.
  • Sample/app/src/main/libs/*.jar — обертка для С++ библиотеки
  • Sample/app/src/main/assets/data/*.se — конфигурационный файл

Все файлы, предоставляемые в виде исходных кодов могут быть изменены на ваше усмотрение.

Описание интеграции

C++ библиотека поставляется в виде бинарных файлов для разных архитектур. Java взаимодействует с ней через JNI(Java Native Interface); обёртка .jar для C++ кода создана с помощью SWIG.

Любой объект, возвращаемый функцией JNI (то есть методами нашей обёртки), — это локальная ссылка, действительная только в рамках вызова метода в текущем потоке. Сам движок при этом продолжает существовать глобально.

При неправильном использовании таких ссылок велика вероятность получить NullPointerException в разные моменты работы приложения. Поэтому старайтесь сразу сохранять результат вызова в нативные Java-объекты, чтобы не хранить ссылки на структуры нашей библиотеки.

Подробнее о правилах работы с JNI: Android docs.

Интеграция

  1. Библиотека. Скопируйте из SDK директорию с бинарными библиотеками jniLibs и поместите ее в ваш проект по пути app/src/main/jniLibs/
  2. Обертка. Скопируйте из SDK файл jni*.jar и поместите его в ваш проект по пути app/src/main/libs/.
  3. Бандл. Скопируйте из SDK файл c расширением *.se и поместите его в ваш проект по пути app/src/main/assets/data/*.se.
  4. В build.gradle (module) подключаем обертку:

    dependencies { implementation(fileTree("libs") { include("*.jar") }) }

  5. Proguard rules. если вы используете оптимизацию кода (minifyEnabled true), добавьте следующие строки в файл proguard-rules.pro, в противном случае возникнут ошибки при сборке проекта в релизной версии.

-keep class com.smartengines.common.* { public <methods>; } -keep class com.smartengines.id.* { public <methods>; }

Подключите этот файл в build.gradle (module).

apply plugin: 'com.android.application'

android {
  compileSdk 36
  ...
  buildTypes {
    release {
      minifyEnabled true
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' /
    }
    debug {
      minifyEnabled false
    }
  }
}
...

Работа с библиотекой

Взаимодействие с библиотекой происходит по следующему сценарию:

  1. Инициализация библиотеки с загрузкой конфигурационного файла.
  2. Создание настроек сессии, определяющих, что именно нужно распознавать.
  3. Подготовка изображения для передачи на распознавание (либо в цикле при обработке видео-потока, либо один раз при распознавании изображения из галереи)
  4. Инициализация сессии и передача в неё изображения.
  5. Разбор результата распознавания.

Если библиотека используется во всём приложении — инициализируйте её один раз при старте процесса в Application.onCreate(),

Если библиотека нужна только в отдельных частях приложения — инициализируйте её в Activity.onCreate().

Для начала загружаем нативную библиотеку

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
)

Создание сессии

Сессия распознавания может быть сконфигурирована для распознавания конкретных типов документов, настройки таймаута, необходимости получить в результате распознавания проективно исправленные изображения и так далее.

// 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
  )

Создание изображения

Независимо от источника изображения (серия изображений с камеры или выбор изображения из галереи) необходимо создать изображение класса se.common.Image.

Передаем сессии одну картинку и сразу получаем результат

fun processPhoto(image: Image) {
  // PROCESS THE IMAGE (long process)
  val result = session.Process(image)
}

При работе с видео потоком обрабатывайте кадры последовательно в рамках одной и той же сессии.

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

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

Терминальность — автоматическая остановка процесса распознавания в видеопотоке. Принимает значение true в двух случаях:

  • добавление новых кадров не приведёт к изменению результата распознавания;
  • исчерпалось ограничение времени сессии, заданное в настройках.

Таким образом вы всегда получаете ответ от системы.

fun processVideoFrame(image: Image) {
  // PROCESS THE IMAGE (long process)
  val result = session.Process(image)
  // Check the result is terminal
  if ( result.GetIsTerminal() ) ... stop the process here
}

Разбор результата

Полученный в результате распознавания результат (объект класса IdResult) содержит все данные документа. Для их получения используются различные методы класса, описанные в документации.

В качестве критерия для проверки наличия результата после завершения (терминальности) сессии рекомендуется использовать метод result.GetDocumentType(). Возвращаемое значение доступно на протяжении всей сессии, при условии, что распознавание выполнялось хотя бы один раз.
Для анализа промежуточных результатов распознавания рекомендуется использовать метод result.GetTemplateDetectionResulsCount(), поскольку он позволяет определить наличие документа в текущем кадре.

Получение текстовых полей документа:

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

Освобождение памяти

Рантайм Java не управляет памятью в C++. Garbage collector не имеет доступа к объектам, которые порождает С++. Большинство классов нашей библиотеки содержат фабричные методы, возвращающие указатели на объекты, выделенные в куче (new, new[], malloc, factory возвращает указатель), поэтому ответственность за освобождение памяти лежит на том, кто пользуется этим объектом!

Обязательно освобождайте ресурсы, как перестаете в них нуждаться. session.Reset(), image.delete(), engine.delete()

Обработка исключений

Наша библиотека может выдавать исключения подклассов se::common::BaseException при неверном вводе данных, некорректных вызовах и других ошибках. Не забывайте их обрабатывать.

Заказать продукт

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

    Т-Банк

    Smart Engines поставляет мобильные и серверные решения по распознаванию документов Т-Банку

    Альфа-Банк

    Альфа-Банк распознает документы клиентов в мобильном приложении с помощью Smart ID Engine

    ВТБ

    ВТБ перешел на российские технологии для распознавания QR-кодов и банковских карт

    Газпромбанк

    Газпромбанк внедрил решение Smart Engines на основе искусственного интеллекта для распознавания QR-кодов

    Заказать продукт

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

      https://smartengines.ru/integracziya-androidArray ( )