Мы, 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)
Sjam
20.12.2017 16:09Спасибо. Нет ли планов добавить поддержку и на go?
SmartEngines Автор
20.12.2017 21:17Планов пока нет, но и проблем с этим мы не видим, тем более потому, что Go поддерживается SWIG-ом. Будет заказчик, который попросит Go — будет и поддержка Go. :)
bano-notit
20.12.2017 16:20+2Классная идея. Сразу вспоминается прикол «не хотите ли проверить свой пароль на наличие в хакерских бд?»
Вообще передавать документы по незащищённым каналам — бич современного народа, а телега для меня не является защищённой, не известно что они там делают с данными и они никаких обязательств по содержанию этих данных в сохранности по сути не берут.
Electrohedgehog
Отличная идея! Простая функция, но классная и полезная, в голове сразу появилось несколько похожих идей. Отдельное спасибо за репозиторий.