Код антикапчи на гитхаб: https://github.com/satels/yandex-captcha
Здесь будут описаны этапы в программе, через которые проходят изображение, а также этапы машинного обучения.
Программа актуальна на осень-зиму 2016 года, после публикации статьи кажется, что яндекс, через некоторое время, поменяет алгоритм генерации капчи.
Имелось всего ~ 10 тыс каптч с известными результатами, какое слово в капче (были свои проблемы, что часть с неправильными результатами, но это опустим), больше половины использовалось для обучения (train) и остальная часть для проверки обучения (test).
Этапы:
- Убираем яндекс логотип.
- Переводим изображение в черно-белое (все оттенки превращаются в чёрный).
- Находим область с точными границами, где находится слово.
- Комментарий: Здесь есть проблема, что помимо слова на всём протяжении картинки имеется линия, которая может являтся продолжением букв, входящих в слово на капче. Поэтому просто так нельзя использовать метод для определения границ слова: центр тяжести (или центр масс). Я определяю границы слова на капче с помощью определения прямых отрезков (линий) на изображении, а именно - вертикальных отрезков (с длиной не меньше заданной) с небольшими отклонениями от вертикали. Таким образом отсекается хвост с шумовой линией. Здесь есть проблема с граничным условием - может немного отсечься лишнее; но это небольшой участок постоянной длины мы можем добавить как константу.
- Определение длины слова в каптче.
- Комментарий: Теперь нужна нейронная сеть для определения длины слова в капче. Итак, у нас имеется единица - очищенная подготовленная картинка со словом с капчи. Создаём свёрточную нейронную сеть (cnn, convolutional neural network). Данный тип сети был выбран, т.к. он отличается большой степенью распознавания необходимых объектов (в нашем случаем длина слова).
- Разбиваем картинку-слово на картинки-буквы.
- Делим слово на равные части в соответствии с кол-вом букв, но каждую границу буквы смещаем на половину длины буквы (по возможности - в зависимости - пограничная ли буква).
- Определение буквы на изображении.
- Получаем набор (set) картинок-букв. Опять же создаём глубокую (deep) свёрточную нейронную сеть.
Вероятности на выходе:
- Вероятность определения длины слова > 93%
- Вероятность определения буквы на картинке > 89%
- Итоговая вероятность в зависимости от длины слова в среднем получается > 63%
Что можно доработать для увеличение вероятности распознавания > 80%
- шумовая линия всё же портит на таком кол-ве данные (на большем кол-ве картинок должно стать лучше, но всё же стоит как-то детектировать - меньше вес давать ей
- большая выборка (проблемы с распознаванием й, щ и ъ)
- поиграться с константой длины для обрезанной картинки (некоторые буквы съедаются - например заместо о - буква с детектиться или заместо а - о)
- добавить паттерны русского языка в conf.RUS_REPLACE - может каких-то не хватает
Я создал готовую web-api систему (запускать в docker контейнере). Код на гитхаб: https://github.com/satels/yandex-captcha
Жду от тех, кто будет пользоваться кодом: напишите пожалуйста README, набор капч могу выслать по почте (satels@gmail.com), готовые модели жду тоже от вас, прикреплю тут.