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

Программа актуальна на осень-зиму 2016 года, после публикации статьи кажется, что яндекс, через некоторое время, поменяет алгоритм генерации капчи.

Имелось всего ~ 10 тыс каптч с известными результатами, какое слово в капче (были свои проблемы, что часть с неправильными результатами, но это опустим), больше половины использовалось для обучения (train) и остальная часть для проверки обучения (test).

 

Этапы:

  1. Убираем яндекс логотип.
  2. Переводим изображение в черно-белое (все оттенки превращаются в чёрный).
  3. Находим область с точными границами, где находится слово.
    • Комментарий: Здесь есть проблема, что помимо слова на всём протяжении картинки имеется линия, которая может являтся продолжением букв, входящих в слово на капче. Поэтому просто так нельзя использовать метод для определения границ слова: центр тяжести (или центр масс). Я определяю границы слова на капче с помощью определения прямых отрезков (линий) на изображении, а именно - вертикальных отрезков (с длиной не меньше заданной) с небольшими отклонениями от вертикали. Таким образом отсекается хвост с шумовой линией. Здесь есть проблема с граничным условием - может немного отсечься лишнее; но это небольшой участок постоянной длины мы можем добавить как константу.
  4. Определение длины слова в каптче.
    • Комментарий: Теперь нужна нейронная сеть для определения длины слова в капче. Итак, у нас имеется единица - очищенная подготовленная картинка со словом с капчи. Создаём свёрточную нейронную сеть (cnn, convolutional neural network). Данный тип сети был выбран, т.к. он отличается большой степенью распознавания необходимых объектов (в нашем случаем длина слова).
  5. Разбиваем картинку-слово на картинки-буквы.
    •  Делим слово на равные части в соответствии с кол-вом букв, но каждую границу буквы смещаем на половину длины буквы (по возможности - в зависимости - пограничная ли буква).
  6. Определение буквы на изображении.
    • Получаем набор (set) картинок-букв. Опять же создаём глубокую (deep) свёрточную нейронную сеть.

 

Вероятности на выходе:

  1. Вероятность определения длины слова > 93%
  2. Вероятность определения буквы на картинке > 89%
  3. Итоговая вероятность в зависимости от длины слова в среднем получается > 63%

 

Что можно доработать для увеличение вероятности распознавания > 80%

  • шумовая линия всё же портит на таком кол-ве данные (на большем кол-ве картинок должно стать лучше, но всё же стоит как-то детектировать - меньше вес давать ей
  • большая выборка (проблемы с распознаванием  й, щ и ъ)
  • поиграться с константой длины для обрезанной картинки (некоторые буквы съедаются - например заместо о - буква с детектиться или заместо а - о)
  • добавить паттерны русского языка в conf.RUS_REPLACE - может каких-то не хватает

 

Я создал готовую web-api систему (запускать в docker контейнере). Код на гитхаб: https://github.com/satels/yandex-captcha

Жду от пользователей кодом - написать  README, набор капч могу выслать по почте (satels@gmail.com), готовые модели жду тоже от вас, прикреплю тут.