Smart IDReader by Smart Engines


Мы, Smart Engines, продолжаем цикл статей про то, как встроить наши технологии распознавания (паспортов, банковских карт и других) в ваши приложения. Ранее мы уже писали про встраивание на iOS и Android, а сегодня мы расскажем про то, как работать с Python-интерфейсом библиотеки распознавания Smart IDReader и напишем простого Telegram-бота.


Кстати, список поддерживаемых нами языков программирования расширился и теперь включает C++, C, C#, Objective-C, Swift, Java, Python, а также такие эзотерические языки, как Visual Basic и, разумеется, PHP. Как и раньше, мы поддерживаем все популярные и многие непопулярные операционные системы и архитектуры, а наши бесплатные приложения доступны для скачивания из App Store и Google Play.


По традиции, демо-версия Smart IDReader SDK для Python вместе с исходным кодом реализации Telegram-бота выложены на Github и доступны по ссылке.


Что нам понадобится


От SDK нам потребуется несколько файлов:


  • Python-интерфейс библиотеки распознавания (pySmartIdEngine.py)
  • Динамическая библиотека С++ ядра распознавания (в случае Linux — _pySmartIdEngine.so)
  • Архив конфигурации (*.zip)

Для написания Telegram-бота мы выбрали telepot.


Взаимодействие с ядром распознавания


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


Подключим библиотеку и сконфигурируем движок распознавания:


# Подключаем python-интерфейс библиотеки распознавания
import pySmartIdEngine as se 

# Путь к файлу конфигурации
smartid_config_path = 'bundle_mock_smart_idreader.zip' 

# Создаем движок распознавания, лучше сделать один раз и держать в памяти
smartid_engine = se.RecognitionEngine(smartid_config_path) 

Теперь можно написать функцию распознавания изображения:


def recognize_image_file(smartid_engine, image_file_path):
    # Получаем настройки по умолчанию и включаем нужные типы документов
    session_settings = smartid_engine.CreateSessionSettings()
    session_settings.AddEnabledDocumentTypes('rus.passport.national')

    # Создаем сессию распознавания
    session = smartid_engine.SpawnSession(session_settings)

    # Распознаем изображение
    result = session.ProcessImageFile(image_file_path)

    # Конвертируем распознанные строковые поля в dict
    recognized_fields = {}
    for field_name in result.GetStringFieldNames():
        field = result.GetStringField(field_name)
        recognized_fields[field_name] = field.GetValue().GetUtf8String()

    # Возвращаем строковое JSON-представление распознанных полей
    return json.dumps(recognized_fields, ensure_ascii=False, indent=2)

Реализация бота для распознавания присланных ему изображений


Мы пойдем по простому пути и воспользуемся примером из документации telepot. Нам нужно написать класс, объект которого будет создаваться на каждый чат, и реализовать в нем функцию on_chat_message. Также в конструктор мы будем передавать ранее созданный движок распознавания, чтобы каждый раз не тратить время на его создание:


import telepot
from telepot.delegate import per_chat_id, create_open, pave_event_space
from telepot.loop import MessageLoop

class SmartIDReaderBot(telepot.helper.ChatHandler):
    def __init__(self, seed_tuple, smartid_engine, **kwargs):
        self.smartid_engine = smartid_engine

        super(SmartIDReaderBot, self).__init__(seed_tuple, **kwargs)

    def on_chat_message(self, msg):
        try:
            content_type, chat_type, chat_id = telepot.glance(msg)

            if content_type in ['document', 'photo']:
                content = msg[content_type] if content_type == 'document'                      else msg[content_type][-1]
                if 'file_id' in content:
                    # Скачиваем файл изображения
                    downloads_dir = 'downloaded_images'
                    os.makedirs(downloads_dir, exist_ok=True)
                    temp_path = os.path.join(downloads_dir,
                        'chat_%d_id_%d_temp.png' % (chat_id, msg['message_id']))
                    self.bot.download_file(content['file_id'], temp_path)

                    # Распознаем изображение
                    recognition_result_str = recognize_image_file(
                        self.smartid_engine, temp_path)

                    # Посылаем сообщение с результатом распознавания
                    self.send_message(recognition_result_str)
            else:
                self.send_message("Send me a photo and I'll recognize it!")
        except Exception as e:
            self.send_message('Exception: %s' % e.message)

    def send_message(self, message):
        self.sender.sendMessage(message)
        print(message)

Наконец, создадим и запустим бота:


# Создаем бота
bot = telepot.DelegatorBot(args.token, [
    pave_event_space()(
        per_chat_id(), create_open,
        SmartIDReaderBot, smartid_engine, timeout=1000000
    )
])

# Запускаем бота
MessageLoop(bot).run_as_thread()

while 1:
    time.sleep(10)

Вместо args.token следует подставить свой уникальный token бота, получаемый после его регистрации. Если вы никогда не создавали бота, то на официальном сайте Telegram есть подробная инструкция.


Заключение


Вот и все! Мы рассказали, как с помощью Python-интерфейса Smart IDReader SDK написать своего Telegram-бота для распознавания документов.


Заметим, что особенностью наших продуктов является их полная автономность — им не нужен интернет. Но если вдруг очень захочется, то с помощью Telegram можно очень просто распознавать документы удаленно. Однако, по российскому законодательству распознавать удаленно можно только свои документы. Чтобы работать с данными документов других людей, необходимо не только стать оператором по обработке и хранению персональных данных, иметь необходимую инфраструктуру для защиты этих данных, но также защищать все телефоны и компьютеры, на которых происходит распознавание. Поэтому, наши коллеги из Sum&Substance с помощью наших библиотек разработали платформу для удаленного распознавания и проверки данных документов, при этом заботясь о юридической стороне вопроса.

Комментарии (4)


  1. Electrohedgehog
    20.12.2017 07:33

    Отличная идея! Простая функция, но классная и полезная, в голове сразу появилось несколько похожих идей. Отдельное спасибо за репозиторий.


  1. Sjam
    20.12.2017 16:09

    Спасибо. Нет ли планов добавить поддержку и на go?


    1. SmartEngines Автор
      20.12.2017 21:17

      Планов пока нет, но и проблем с этим мы не видим, тем более потому, что Go поддерживается SWIG-ом. Будет заказчик, который попросит Go — будет и поддержка Go. :)


  1. bano-notit
    20.12.2017 16:20
    +2

    Классная идея. Сразу вспоминается прикол «не хотите ли проверить свой пароль на наличие в хакерских бд?»
    Вообще передавать документы по незащищённым каналам — бич современного народа, а телега для меня не является защищённой, не известно что они там делают с данными и они никаких обязательств по содержанию этих данных в сохранности по сути не берут.