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

Начну с краткого интро. Мы зарабатываем тем, что проводим промо-акции для производителей и продавцов разнообразных потребительских товаров. Как правило, это что-то из разряда «купи товар – найди код – отправь его нам – выиграй приз». Основной наш продукт — это платформа, которая эти коды генерирует, принимает, обрабатывает, помогает коммуницировать с участниками, выплачивает бонусы и делает еще много чего интересного.

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

Первым делом я зарегистрировался во всех акциях с чеками, о которых узнал (ну если честно не во всех, где-то в районе второго десятка мне надоело). Чеков у меня, как вы догадываетесь, не было и я решил вместо чека использовать фото котика на абстрактном фоне. Каково же было мое удивление, когда во всех акциях, кроме одной, моего котика приняли и допустили меня до розыгрыша призов. А кое-где даже выдали моментальный приз в виде промо-кода в онлайн-библиотеку. Честно говоря, в той одной акции котика тоже приняли, но обещали направить его на модерацию и в течение 8 (!) часов решить вопрос о моём участии в акции.

Такой вариант нам явно не подходил. Во-первых, допускать человека до розыгрыша по любому фото не хорошо. Он может сколько позволит платформа раз загрузить фото одного и того же чека, тем самым многократно повысив свои шансы на получение выигрыша. Когда одна из этих заявок выигрывает, предъявляется оригинал того самого единственного чека и забирается приз. Конечно, есть шанс выиграть дважды и выдать себя, но это мы уже увлеклись. Во-вторых, 8 часов не давать человеку обратной связи выглядит издевательски в мире, где посетитель, проведший на сайте более 15 секунд, считается целевым. В-третьих, давать приз за фото котика означает показать себя не очень компетентным организатором. Кстати, вот он.



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

К тому моменту появился запрос от клиента. Перед нами стояла задача провести акцию для крупной сети розничных магазинов. Забегая вперед, скажу, что принимали до 1000 регистраций в день. Чтобы претендовать на призы в акции вам нужно было в определенный промежуток времени купить чего-нибудь на сумму от N руб. и обязательно оплатить покупку картой VISA. Фото полученного при покупке слипа следовало загрузить к нам на промо-сайт. Если вы признавались победителем, вы должны были предъявить слип и карту VISA на кассе и забрать приз. Одно фото – один шанс на победу. Победитель вычисляется среди всех участников, загрузивших корректные слипы, по специальной формуле. Наша задача на данном этапе: принять слип и допустить/не допустить человека до участия в розыгрыше. При этом желательно по максимуму отсечь хитрецов, которые могут пытаться подсунуть нам один слип дважды, подсунуть слип, напечатанный до начала акции и еще много всего интересного включая, но не ограничиваясь фото котика.

Многократное тестирование продукта крупной компании показало, что он определяет сумму покупки, тип карты, номер карты, время и дату печати слипа. И вроде вот оно: дубликаты отметаем (для этого вычисляя хеши распознанных параметров и самой картинки), сумму, дату, платежную систему и номер карты распознаем. Правда, распознается с ошибками… и не все.

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

Нам пришлось пойти на первый компромисс: просим участника руками ввести сумму покупки и последние 4 цифры номера карты. Далее если то, что ввел человек и то, что распознала машина, совпало, а платежная система и дата печати слипа корректны, допускаем участника к розыгрышу.
Посчитали, оказалось, что допускаем мы только 71% слипов. Остальные 29% это некорректные либо некачественные изображения и корректные, но некорректно распознанные изображения в примерном соотношении 50/50.

Как быть с этими 14,5% чеков, отклоненных ошибочно? Решение пришло довольно быстро, стали отправлять на ручной аппрув в дружественный контакт-центр. Из минусов: дорого и долго. Если 71% счастливчиков получали результат в течение минуты, то этим людям пришлось сообщать об ожидании до 8 часов. Было решено попытаться нормализовать результаты распознавания в нашей системе.

Включаем аналитику: вручную сверяем данные на фото и результат распознавания. Результат распознавания прилетает следующим образом: отдельно поля «дата», «сумма» и т.д. и отдельно полный текст, то есть вообще все что было найдено на изображении. Зачастую данные, не содержащиеся в одном из первых полей, можно было отыскать в полном тексте глазами. По итогу анализа нескольких сотен слипов решили делать следующее:

1) Отличаем чек от слипа: среди всех принятых слипов ищем слип с максимальным количеством строк. Для любого отклоненного (по любой причине) документа считаем количество строк, если оно превышает рассчитанный ранее максимум, говорим человеку «Возможно, вы пытаетесь загрузить чек, а не слип. Сфотографируйте слип отдельно от чека и повторите попытку». Таким образом человек лучше понимал, что не так с его фото.

2) Если не распознана дата: пробуем искать в полном тексте фрагмент по маске «ХХ/ХХ/ХУ», где Х-любое число, а У – любой символ. При нахождении фрагмента У менять на 6 (или 7 в зависимости от года проверки), найденный фрагмент считать датой печати слипа. Да-да, косячила система в основном на последней цифре даты. Выиграли 2%.

3) Если не распознана сумма: искать в полном тексте по маске «ZХХХХ.ХХ RU», где Х-любое число, а Z – любой символ в том числе пробел или отсутствие символа. Найденный фрагмент сравнить с тем, что ввел участник. При расхождении поочередно заменить все символы 6 на 8 в найденном фрагменте и сравнить с тем что ввели. Почему-то машина часто путала именно 6 и 8, причем не 8 и 6, а именно 6 и 8. Выигрыш порядка 3%.

4) Номер карты: искать в полном тексте по маске «** XXXX», где Х-любое число. Между символами Х могут стоять пробелы либо знаки препинания, их отбрасываем. Полученное число сравниваем с введенным вручную номером карты. + 1%.

5) Карта оплаты: искать в полном тексте один из фрагментов: «Карта:V», «Карта: V», «Карта’V», «VISH». При нахождении считать карту картой VISA. + 3%.

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

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

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


  1. klev
    07.02.2017 21:15
    +1

    Тема очень интересная.
    А можно узнать, какие технологии, сервисы или библиотеки были использованы?


    1. Pavel_SD
      08.02.2017 09:56
      +1

      С одной стороны наша платформа, не уверен, будет ли рекламой если я тут укажу ее название.
      Сама платформа в основном самописаная, содержит очень мало заимствований и сторонних компонентов. Вся логика и БД на стороне платформы. В качестве средств ввода-вывода в данной акции подключались промо-сайт на самописной CMS и контакт-центр для «горячей линии». Еще использовался SMS-шлюз, тоже собственный, он подключается к крупным провайдерам, а те же уже напрямую к операторам.
      В других акциях к ним могут добавляться мобильные приложения, платежный шлюз, социальные сети и мессенджеры.
      С другой стороны использовался один из популярных OCR-сервисов, жду от них ответа, можно ли тут написать название.


      1. vitalets
        08.02.2017 16:44

        Спасибо за статью!
        Да, было бы интересно узнать название OCR-сервиса!


        1. Pavel_SD
          08.02.2017 18:56
          +2

          ABBYY Cloud OCR SDK http://ocrsdk.com/


          1. vitalets
            08.02.2017 19:03

            Спасибо!


  1. alexmay
    07.02.2017 22:53
    +4

    Хм… а статья -то о чем?
    О том, что вы научились данные из одного ПО обрабатывать в другом, следуя набору правил?


  1. Welran
    08.02.2017 07:05
    +1

    Такого милого котика, как не допустить до конкурса. Всё правильно сделали!


  1. KivApple
    08.02.2017 07:56

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


  1. DR17
    08.02.2017 09:30

    1) «пошли к профессионалам – одной известной компании» А название раскроете?
    2) Как бороться с подделками? Можно самому печатать такие слипы и получать бонусы. Или гелевой ручкой исправлять 6 до 8 или 0 до 8 или 5 до 6 итд.
    3) Данная точность для вас приемлема? Почему?


    1. Pavel_SD
      08.02.2017 10:16
      +1

      1) Жду от них разрешения.
      2) Это нельзя на 100% исключить. Но с таким слипом вам не выдадут приз. К тому же мы ежедневно вручную проверяли некоторое количество слипов, отслеживали подозрительную активность участников. А подделка слипов это уже, думается мне, уголовно наказуемое деяние.
      Вообще существуют целые сообщества так называемых призоловов и борьба с ними тема отдельной статьи). Некоторые действуют профессионально. Например, в одной из акций с уникальными кодами (вместо чеков) из типографии клиента похитили бобины с этикетками (мы так думаем) и устроили нам атаку с пула в несколько сотен очень похожих друг на друга номеров. Причем попытки блокировать по номера маске приводили к тому, что страдали рядовые участники.
      3) Потому что мы сделали максимум того что могли и не знаем иных способов с более высокой точностью. К тому же есть подстраховка в виде ручного распознавания.


      1. DR17
        10.02.2017 13:34

        А где ваша система внедряется/внедрена?


        1. Pavel_SD
          10.02.2017 14:25

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


    1. Pavel_SD
      08.02.2017 18:57
      -1

      1) ABBYY Cloud OCR SDK со ссылкой http://ocrsdk.com/


  1. EnigMan
    08.02.2017 09:39
    +4

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


    1. LumberJack
      08.02.2017 14:43
      -1

      C 1 февраля 2017 года, если точнее.


  1. oops1
    08.02.2017 10:09

    А не проще/дешевле было воспользоватся сервисами распознавания
    такие уже есть но заточены под капчу
    первый попавший в гугле сервис распознавания капчи
    7 — 9 секунд на распознавание 18 руб за 1000 капч


    1. Pavel_SD
      08.02.2017 10:24
      +1

      Не вижу, чем это лучше заточенного под чеки (пусть и не русские пока) OCR-сервиса которым мы пользовались.
      С ними во-первых нужно договориться чтобы они принимали не каптчу размером одна строка, а некий документ. К тому же документ структурированный и результат тоже должен быть структурирован.
      Если они используют ручное распознавание (что довольно распространено у них), то где гарантия что распознавать будет человек который разберет язык и поймем в каком месте какой параметр указан.


      1. oops1
        08.02.2017 10:27

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

        я так понимаю есть и русские сервисы, которые принимают русскую капчу


        1. Pavel_SD
          08.02.2017 10:42
          +1

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


  1. Ermak
    08.02.2017 17:06

    Так есть же ABBYY Cloud OCR SDK, специально заточенное под чеки:
    http://ocrsdk.com/documentation/quick-start/receipt-recognition/


    1. Pavel_SD
      08.02.2017 18:57

      С ними и работали)


  1. BalinTomsk
    08.02.2017 20:16

    На самом деле хочется иметь черную коробочку возле входной двери, имющую щелку для чека, чек всосется, отсканируется и скрутится на барабан с другими чеками.

    Раз в месяц катушка с чеками снимается и кладется в пакетик на хранение.

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

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