Распознавание чеков и внесение их в 1с. Сканирование QR-кода на чеке и импорт в программу

17.04.2019

В 12-ой серии 4-ого сезона "The Big Bang Theory" Шэлдон и компания решили замутить стартап - приложение для iPhone, распознающее и решающее физические уравнения по фотографии. Задача, как мне кажется, очень сложная с технической точки зрения, требующая навыков во многих областях. На сколько мне известно, такого приложения в реальности не существует, но у новоявленных стартаперов на эту программу ушел всего один эпизод. Вспомнилась мне эта серия не просто так. Несмотря на то, что уравнений я не решаю, могу рассказать несколько интересных вещей из области мобильных приложений с распознаванием, призванных облегчить повседневную жизнь.

Современный смартфон является настолько сложным и функциональным устройством, что ему становится под силу выполнять задачи, которые раньше решались только на ПК либо же вообще вручную. Главное преимущество смартфона - это его компактность, способность всегда оказаться под рукой и быстро выполнить поставленную задачу. Вполне возможно, что ожидаемая в ближайшие годы мобильная революция, все-таки произойдет и компактные гаджеты постепенно вытеснят громоздкие ПК из бытового использования. А пока, стартаперы, воодушевленные новыми возможностями смартфонов, клепают новые сервисы.

Что ж, раз уж пошло такое веселье, почему бы не поучаствовать, тем более меня уже очень долгое время мучала одна идея, которую я никак не решался реализовать. Лет 5 назад, когда у меня появился первый смартфон с камерой, я начал осознавать, на сколько велики возможности мобильных платформ. У меня был телефон на Symbian, в то время эта ось была фактически монополистом, кто бы мог подумать, что уже через несколько лет от былой славы ничего не останется. Все-таки в очень интересное время мы живем, титаны и новички умирают и рождаются в течение пары лет. Принципиальной разницы в платформах для мобильных устройств лично я не вижу. Главное, что на любом смартфоне сохраняется основной принцип - открытость архитектуры, а значит, есть возможность написания любого приложения, которое могло бы как-то пригодиться. Поскольку смартфон всегда в кармане, то возникает целая ниша приложений, которые должны быть под рукой, в прямом смысле этого слова.

Еще до того, как у меня появился смартфон, я услышал об одной замечательной идее. Она формулировалась очень просто: "почему бы не использовать телефон для распознавания магазинных чеков". Люди ленятся записывать свои расходы, а чеки просто выбрасывают. Если заменить ежедневный учет финансов несколькими простейшими действиями со своим телефоном, то вероятно многие бы согласились вести домашнюю бухгалтерию. Как обычно и бывает, простая задача требует сложного решения. Сразу стало понятно, что проблема невероятно комплексная, требующая реализации на нескольких взаимодействующих уровнях. Попыток реализации такого механизма в мире было очень мало, а в России и вовсе не было. И раз уж у меня появилась возможность принять этот технический вызов, я решил сделать это.

Так родился проект "33 бакса" - революционная система учета личных финансов, основной фичей, которой является фотографирование и распознавание магазинных чеков. Работать над этим проектом мы начали полгода назад, с тех пор было сделано несколько прототипов. Текущая версия является третьей. По сути это тоже прототип, но уже вполне работоспособный, а главное он мне самому нравится все больше. Поскольку задача, комплексная, то и реализованная система включает в себя несколько взаимодействующих модулей:

1. Ядро распознавания под названием iclean - самый сложный с технической точки зрения модуль, являющийся отдельным приложением, написанным на С++. Он включает в себя несколько сторонних библиотек по обработке и коррекции изображения, несколько сторонних библиотек OCR для получения голого текста, модуль определения структуры чека и извлечения данных. Что касается обработки изображения и OCR, здесь все понятно и тривиально. За исключением того, что в iclean используется не одна OCR, а комбинация 3-х, что позволяет повысить качество распознанного текста даже на очень плохих снимках, получаемых с мобильного телефона. С извлечение данных из полученного текста все гораздо сложнее. Поскольку существует огромное количество типов чеков, нужно было создать механизм, который был бы независим от структуры и расположения полей. Между прочим, в чеках из супермаркетов, этих полей очень много: название магазина, адрес, телефон, сайт, ИНН, список товаров с указанием цен. Всю эту информацию нужно было из чека доставать, для этого был сделан двухступенчатый механизм. На первой ступени текст прогоняется по имеющимся в системе шаблонам. Если найден шаблон с удовлетворительной степенью схожести, то он используется для выявления всех возможных полей. Если шаблон не найден, то подключается вторая ступень, на которой определяются только три поля по ключевым словам: сумма, дата, название магазина. Сам текст, не попавший ни под один имеющийся шаблон, сохраняется и на его основе создается новый шаблон. Таким образом, количество шаблонов в системе постоянно увеличивается и количество поддерживаемых чеков соответственно растет.

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

  • Загружать чеки
  • Добавлять расходы вручную
  • Редактировать распознанные данные (в том числе вносить информацию о магазинах и товарах)
  • Просматривать список расходов, фильтровать, искать, сортировать
  • Просматривать различные графики (в том числе статистику по товарам и магазинам)

3. Мобильные клиенты - приложения, которые работают на смартфонах пользователя. Опять же только базовые функции по вводу расходов: можно сфотографировать чек и отправить его в свой аккаунт на сайте, полученные распознанные данные можно отредактировать, можно ввести расход вручную. Сейчас реализованы клиенты для двух платформ: Symbian и Android. Скачать приложения можно через магазины:

А теперь о том, чего стоит ожидать, если проект оправдает надежды:

  1. Чем больше будет загружаться чеков, тем точнее будет распознавание, поскольку будет увеличиваться количество шаблонов. Кроме того, будет лучше работать авто корректировка названий товаров и магазинов.
  2. Поскольку будет накапливаться база данных товаров и магазинов, то пользователь сможет получать рекомендации по уменьшению своих расходов. К примеру, он сможет узнать, где купить аналогичный товар дешевле, или оценить уровень цен в том или ином магазине.
  3. Опять же на основе базы данных товаров можно будет сделать сервис аналогичный Яндекс Маркету, с перечислением стоимости товара в различных магазинах. В отличие от Яндекс Маркета, в этом рейтинге цен будут участвовать абсолютно все магазины, независимо, есть ли у них прайс-лист в электронном виде или нет.

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

Это инструкция для iOS.

Такие чеки можно импортировать в программу Alzex Finance. Для начала нужно установить программу Проверка кассового чека ФНС России. Проверить валидность чека можно и без регистрации, но чтобы скачать чек, нужно завести аккаунт в программе (указать телефон и ввести код из полученной смс). Далее нужно сканировать QR-коды и получать чеки.

Откройте программу "Проверка чеков".
Для экспорта полученных чеков в главном меню программы выберите пункт "Получение выписки"

Убедитесь, что получили все чеки прежде чем экспортировать их в программу! У каждого чека должен быть зеленый значок и надпись "Чек получен". Надпись "Чек корректен" означает, что чек правильный, но еще не скачан из базы данных налоговой. Такой чек нужно открыть и нажать кнопку "Получить чек".

Выберите интервал времени и формат данных json. Чтобы получить данные за текущее число оставьте оле "До" пустым. Нажмите кнопку "Получить выгрузку". Подождите пока загрузятся чеки.

Не пугайтесь надписи "Не поддерживаемый тип просмотра data", просто подождите и чеки загрузятся


Нажмите кнопку "Экспорт".

Выберите из списка программу Alzex Finance.
Можно выбрать чеки, которые будут импортированы. Чеки, которые в программе уже есть, по умолчанию пропускаются.

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

Все импортируемые чеки попадают в раздел "Неподтвержденные транзакции". Программа подберёт категорию для каждой позиции в чеке на основе ранее введенных транзакций. Например, если в базе есть транзакция с описанием "Молоко" и категорией продукты, все транзакции, в которых встречается слово "Молоко" будут отнесены в категорию "Продукты". Вам останется только указать категории для транзакций, которые не удалось распределить автоматически, а также необходимо выбрать счет и сменить статус чека с "не подтвержденный" на "подтвержденный"

Если у вас есть замечания или предложения по работе программы, мы с удовольствием их выслушаем!

FinPix - это не просто уникальный сканер кассовых чеков на русском языке, а приложение для полноценного учета домашних финансов.
Особенности :

  • Распознавание кассовых чеков на русском языке. Приложение распознает отдельные позиции в чеке, выделяет название товара, цену, количество, скидку, стоимость;
  • Распознавание банковских СМС. Если какие-то СМС от банков не распознаются, Вы можете присылать нам примеры из приложения и мы добавим поддержку новых форматов;
  • Учет доходов, расходов, переводов между счетами, а также на их основе долгов, кредитов, депозитов, обменов валют;
  • Ведение счетов, отслеживание остатков по ним;
  • Ведение нескольких отдельных бюджетов внутри приложения;
  • Использование категорий и подкатегорий для классификации расходов. Для удобства Вы можете настроить, к каким категориям относятся отдельные товары, тогда FinPix будет определять категорию для знакомых товаров автоматически;
  • Указание операций в любых валютах ISO 4217, автоматический пересчет значений в разные валюты по курсу на дату расхода (необходимые курсы загружаются с сайта ЦБ РФ);
  • Анализ структуры и динамики доходов и расходов на соответствующих диаграммах;
  • Просмотр журнала операций в виде списка с возможностью фильтрации по категориям и периодам, счетам и источникам доходов, текстовый поиск операций;
  • Экспорт основных данных приложения в файл xlsx, импорт данных в том же формате, что может использоваться как для создания резервных копий, так и для обмена данными при совместном ведении семейного бюджета несколькими членами семьи;
  • Данные в экспортированном файле xlsx адаптированы для анализа в офисных приложениях, в т.ч. в файле сразу создана сводная таблица по расходам в разрезе категорий и периодов;
  • FinPix является бесплатным приложением, единственная платная функциональность в нем - выгрузка названий товаров в чеках при экспорте в xlsx (не касается тех расходов, которые были внесены в приложение вручную или импортированы).

Примечание : процесс распознавания чека по фотографиям может занимать продолжительное время - до нескольких минут. Длительность обработки зависит от качества самого чека, от качества фотографий, а так же от производительности устройства. Когда запущено распознавание чека, можно продолжить работу с приложением, в т.ч. фотографировать другие чеки. При этом приложение будет распознавать чеки друг за другом. Приложение FinPix само никуда не отсылает чеки - распознавание происходит прямо на Вашем телефоне или планшете, т.ч. данные о Ваших расходах остаются только Вашими .

Начните использовать FinPix для ведения домашней бухгалтерии, сканируйте чеки, и Вы без больших усилий узнаете структуру своих расходов. Кроме того, попутно Вы сформируете собственную базу данных цен на товары в разных магазинах, сохраните для себя информацию, какие товары, сколько и где Вы покупали ранее, сможете отслеживать персональную инфляцию. Делаете ремонт, едете в отпуск - сохраняйте детализированные расходы, чтобы иметь возможность точно спланировать их в следующий раз.
Скачать приложение FinPix учет и сканер чеков на Андроид вы можете по ссылке ниже.

Иван Ожиганов Апрель 7, 2016

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

Мы в очередной раз убедились в эффективности использования свёрточных нейронных сетей в процессе работы над проектом по распознаванию кассовых чеков. Объектом исследования выступили кассовые чеки из ряда российских торговых точек, с текстом на кириллице и латинице. При этом разработанная система может быть легко адаптирована под распознавание кассовых чеков из других стран, с текстом на других языках. Рассмотрим проект в деталях, чтобы показать принцип действия полученного решения.

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

Обзор проекта

Задача распознавания чеков состоит из нескольких этапов:

1. Препроцесссинг
Поиск чека на изображении
Бинаризация
2. Выделение текста
3. Распознавание
4. Извлечение необходимой семантической составляющей чека

Реализация

1. Препроцессинг

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

1.1. Поворот изображения и поиск чека на нём

Задачу поиска чека мы выполняли при помощи следующих методов:

  • Адаптивная бинаризация с высоким порогом
  • Свёрточная нейронная сеть
  • Классификатор с признаками Хаара
Поиск чека при помощи адаптивной бинаризации
с высоким порогом

Рис. 1. Изначальный вид чека

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

Для упрощения задачи поиска картинка сначала поворачивается так, чтобы строки располагались максимально близко к горизонтальному положению (Рис. 2). Алгоритм поворота необходим, чтобы максимизировать дисперсию суммы яркости по строкам. Максимум достигается, когда строки расположены горизонтально.

Рис. 2. Поворот чека

Для поиска чека мы использовали функцию adaptive_threshold из библиотеки scikit-image. Это адаптивная бинаризация с большим порогом, которая оставляет пиксели белыми в областях с высоким градиентом, а более однородные области становятся черными. Таким образом, при достаточно однородном фоне остаётся небольшое количество белых пикселей, для которых мы ищем описанный прямоугольник. В результате полученный прямоугольник (Рис. 3) включает в себя область с чеком и минимальное количество фона.

Рис. 3. Найденная область с чеком

Поиск чека свёрточной нейронной сетью

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

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

Представляем вам результаты работы сети:

Рис. 4. Примеры работы свёрточной нейронной сети на поиск углов чека

Поиск чека каскадным классификатором с признаками Хаара

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

Примеры работы каскадного классификатора с признаками Хаара:

Рис. 5. Положительные результаты работы каскадного классификатора с признаками Хаара

Рис. 6. Ложноотрицательное и ложное срабатывания классификатора с признаками Хаара

1.2. Бинаризация

Для бинаризации используется тот же adaptive_threshold, окно достаточно большое, чтобы оно содержало и текст, и фон (Рис. 7).

Рис. 7. Бинаризация чека

2. Выделение текста

2.1. Выделение текста методом связных компонент

Первый этап выделения текста – это поиск связных компонент. Мы реализовали его с помощью функции findContours из OpenCV. Большинство связных компонент в самом деле являются символами, но некоторые – остатки шума после бинаризации. Мы отсеяли их при помощи фильтров по максимальной/минимальной площади. Для составных символов применили алгоритм объединения связных компонент (:, Й, =). После этого символы объединяются в слова при помощи поиска ближайших соседей. Принцип поиска ближайших соседей: для каждого символа ищутся несколько ближайших соседей, затем из них выбирается наиболее подходящий кандидат на присоединение справа и слева. Алгоритм повторяется, пока не останется символов, не принадлежащих словам (Рис. 8).

Рис. 8. Поиск связных компонент и формирование слов (слова выделены одним цветом)

Рис. 9. Формирование строк (строки выделены одним цветом)

Недостаток этого алгоритма состоит в том, что он не способен корректно распознавать слова со слипшимися или разорванными буквами.

2.2. Выделение текста при помощи сетки

Мы заметили, что почти во всех чеках текст моноширинный. Это значит, что можно нарисовать на чеке сетку так, чтобы линии сетки проходили между символами:


Рис. 10. Пример сетки

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

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

Рис. 11. Пример поиска связных компонент

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

График этой формулы выглядит следующим образом:

Рис. 12. График функции в формуле

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

Геометрическое искажение было параметрезированно с помощью функции RectBivariateSpline из модуля scipy в python. Оптимизация осуществлялась с помощью функции minimize из модуля scipy.

Рис. 13. Пример правильно найденной сетки

Рис. 14. Пример неправильно найденной сетки

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

3. Распознавание текста

3.1. Распознавание текста, найденного методом связных компонент

Распознавание текста производится при помощи сверточной нейросети, обученной на шрифтах, вырезанных с чеков. На выходе из сети мы имеем вероятности для каждой буквы и берем несколько первых вариантов, которые в сумме дают близкую к 1 вероятность (99%). Далее рассматриваем все возможные варианты составления слов из полученных букв и проверяем их по словарю. Это позволяет улучшить точность распознавания, исключая ошибки среди похожих символов (З и Э).

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

3.2. Распознавание слова целиком

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

  • при помощи рекуррентной нейронной сети вида LSTM;
  • при помощи равномерной сегментации.
LSTM

Для сложных случаев мы решили использовать нейронную сеть вида LSTM, чтобы распознавать все слово целиком, опираясь на опыт исследований в статьях “Reading Scene Text in Deep Convolutional Sequences ” и “Can we build language-independent OCRusing LSTM networks? ”. Для этой цели мы взяли библиотеку OCRopus .

Использовав моноширинные шрифты, мы подготовили искусственную выборку для обучения (рис. 15).


Рис. 15. Примеры искусственной выборки

Обучив сеть, мы протестировали её на валидационной выборке. Результаты тестирования показали, что сеть обучилась хорошо. Тогда мы проверили её на реальных чеках. Ниже представлены результаты:

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

Мы решили добавить различные искажения в обучающую выборку, для того чтобы приблизить её к словам, получаемым с чеков (Рис. 16).


Рис. 16. Примеры искусственной выборки

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

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

Мы предполагаем, что при одном шрифте и с малыми искажениями такая сеть работала бы намного лучше.

Равномерная сегментация

У нас возникла идея разбить слово на символы равномерно, поскольку шрифт на чеках моноширинный. Для этого необходимо знать ширину символа в слове. Для каждого чека оценивается мода ширины символа. Если распределение ширин символов бимодальное (Рис. 17), то выбираются две моды и для каждой строки определяется своя ширина.


Рис. 17. Пример бимодального распределения ширин символов в чеке

После того как мы получаем примерную ширину символа в данной строке, мы делим длину слова на ширину символа и получаем примерное количество букв. Затем делим длину слова на полученное примерное количество букв плюс-минус один:

Рис. 18. Процесс поиска оптимальной сегментации

И выбираем наилучший вариант разбиения:

Рис. 19. Оптимальная сегментация

Точность такой сегментации весьма высока.

Рис. 20. Пример корректной работы алгоритма

Но иногда мы наблюдали, что алгоритм работает не совсем корректно:

Рис. 21. Пример некорректной работы алгоритма

После сегментации каждый фрагмент отправляется в свёрточную нейронную сеть и распознаётся.

4. Извлечение необходимой семантической составляющей чека

Поиск покупок в чеке совершается при помощи регулярных выражений. Для всех чеков есть одна общая особенность: цена покупок записана в формате XX.XX, где Х – цифра. Таким образом можно извлечь строки с покупками. ИНН ищется по 10 цифрам и проверяется по контрольной сумме. Имя держателя карты ищется в формате NAME/SURNAME.

Рис. 22. Результаты извлечения необходимой семантической составляющей чека

Заключение

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

Работа над проектом продолжается. Мы занимаемся улучшением качества на каждом этапе распознавания и оптимизацией отдельных алгоритмов. На данный момент система с высокой точностью распознаёт чеки хорошего качества – без слипшихся и разорванных букв. Чеки со слипшимися и разорванными буквами распознаются несколько хуже.

Такие чеки можно импортировать в программу Alzex Finance. Для начала нужно установить программу Проверка кассового чека Проверить валидность чека можно и без регистрации, но чтобы скачать чек, нужно завести аккаунт в программе (указать телефон и ввести код из полученной смс). Далее нужно сканировать QR-коды и получать чеки.

Откройте программу "Проверка чеков".
Для экспорта полученных чеков в главном меню программы выберите пункт "Получение выписки".

Убедитесь, что получили все чеки прежде чем экспортировать их в программу! У каждого чека должен быть зеленый значок и надпись "Чек получен". Надпись "Чек корректен" означает, что чек правильный, но еще не скачан из базы данных налоговой. Такой чек нужно открыть и нажать кнопку "Получить чек".

Выберите интервал времени и формат данных json, нажмите кнопку "Запросить"

Возможно, нужно будет выбрать программу для просмотра файлов json, выберите Alzex Finance.

Готово! Все импортируемые чеки попадают в раздел "Неподтвержденные транзакции". Программа подберёт категорию для каждой позиции в чеке на основе ранее введенных транзакций. Например, если в базе есть транзакция с описанием "Молоко" и категорией продукты, все транзакции, в которых встречается слово "Молоко" будут отнесены в категорию "Продукты". Вам останется только указать категории для транзакций, которые не удалось распределить автоматически, а также необходимо выбрать счет и сменить статус чека с "не подтвержденный" на "подтвержденный".

Если программа написала что найдено 0 транзакций, или невозможно открыть файл, то вероятно чек еще не получен (магазин пока не отправил его в налоговую). В разделе "Мои чеки" можно посмотреть статус чека.

Также есть возможность экспортировать и отдельный чек. Откройте чек, нажмите кнопку с тремя точками в правом-верхнем углу и выберите пункт "Отправить чек". Далее выберите тип "json" и в появившемся меню выберите программу "Alzex Finance".

Если у вас есть замечания или предложения по работе программы, мы с удовольствием их выслушаем!