Категория: Linux
Одной из самых сложных задач для поисковых систем является распознавание изображений. Компания Яндекс довольно давно занимается этим вопросом - еще в 2008 году популярный поисковик научился искать портреты среди картинок. Последнее время компания занималась реализацией технологии компьютерного зрения "Сибирь", с помощью которой можно было по загруженному изображению найти в Яндексе похожие картинки. А сегодня российская компания представила дополнительную функцию распознавания для хранилища Яндекс.Диск. Теперь пользователи сервиса смогут искать изображения, на которых содержится интересующий их текст.
Таким образом, результаты поиска теперь содержат изображения, документы и папки, релевантные запросу. Работа сервиса основана на принципе искусственной нейронной сети. Сначала классификатор отбирает изображения, на которых присутствует текст, а затем приступает к углубленному анализу результатов. На этом этапе применяется ещё одна нейронная сеть - теперь машина распознает линии, содержащие текст. Линии в дальнейшем разбиваются на отдельные символы, после чего алгоритм подбирает наиболее подходящие буквы или цифры. Если из отобранных символов получается известное слово, то машина принимает его за результат.
Яндекс.Диск распознает отсканированные листы на русском языке с точностью 80%, Для фотографий с надписями показатель равен 63,2%, а скриншоты сервис распознает с практически 100-% точностью. На данный момент, Яндекс.Диск умеет распознавать текст на форматах JPEG, GIF и PNG. Список языков распознавания включает английский, украинский, турецкий и русский.
Диск Yandex«Яндекс» объявила о запуске функции, которая позволит пользователям сервиса «Яндекс.Диск» распознавать текст на изображениях, хранящихся в облаке. С ее помощью можно легко находить нужные изображения форматов JPEG, GIF и PNG, содержащие текст поискового запроса.
«Когда на Диске тысячи фотографий, разложенных по разным папкам, поиск по текстам позволит быстро найти среди них нужную. Например, скан договора с названием вроде scan723.JPG или фотографию визитки человека, с которым понадобилось связаться. Искать можно не только документы, но и любые фотографии, которые сделаны для того, чтобы сохранить текст, будь то объявление на двери подъезда или любопытный рекламный плакат в метро», – говорится в заявлении «Яндекса».
В основе поиска текстов на изображениях лежит технология оптического распознавания символов, способная распознавать текст на разных по виду, содержанию и качеству картинках.
Система включает в себя классификатор картинок и модуль распознавания. Сначала классификатор анализирует все изображения, отбирая те, на которых обнаруживается текст. Когда изображения с текстом отобраны, алгоритм находит на них линии, предположительно содержащие текст, а затем отбираются только те линии текста, в которых алгоритм уверен.
На следующем этапе модуль распознавания разбивает линии текста на отдельные символы. Для каждого символа выбирается несколько наиболее вероятных вариантов распознавания. После этого в дело вступает языковая модель – алгоритм принимает решение, какой из символов-кандидатов подходит лучше всего.
Языковая модель опирается на словари и учитывает не только сходство символов с теми, что знает система, но и контекст. Если из нескольких вероятных символов складывается известное системе слово, то она принимает решение, что на картинке написано именно оно, даже в том случае, если некоторые символы-кандидаты в этом слове менее вероятны.
В сообщении отмечается, что точность распознавания текста зависит от типа изображения, его четкости, фона, на котором находится текст, и многих других факторов. Например, для отсканированных документов точность распознавания текстов на русском языке составляет около 80%, для фотографий с надписями – 63,2%, а для скриншотов приближается к 100%. Помимо русского языка система также распознает английский, украинский и турецкий.
Присоединяйтесь к нам в Twitter. ВКонтакте. Facebook. Google+ или через RSS. чтобы быть в курсе последних новостей из мира Apple, Microsoft и Google.
Вот (http://images.yandex.ru/search?p=149&ed=1&text=%D0%B6%D0%B5%D0%BB%D1%82%D1%8B%D0%B5%20%D0%BB%D0%B8%D1%81%D1%82%D1%8C%D1%8F&spsite=fake-015-818874.ru&img_url=1522-msk.ucoz.ru%2F_fr%2F1%2F2551801.jpg&rpt=simage&nl=1)
Конечно, скоро выдача будет несколько иной. Но пример показывает, что Я узнает рамку и разные подписи.
Уменьшаем битность, вычисляем взвешенную последовательность цветов (по горизонтали или вертикали, а где нет быстрой смены цветов в перпендикулярной плоскости, пишем в базу как хеш-код), например, 0.3 синих -- 0.3 черных -- 0.2 зеленых -- 0.2 синих == 1 линия. И так несколько линий.
Если с очередной картинки полученное множество весов является подмножеством уже занесенного в базу (и наоборот), то это вероятно дубль. Чем больше совпадений множеств, тем вероятнее, что это дубль.
Вот (http://images.yandex.ru/search?p=149&ed=1&text=%D0%B6%D0%B5%D0%BB%D1%82%D1%8B%D0%B5%20%D0%BB%D0%B8%D1%81%D1%82%D1%8C%D1%8F&spsite=fake-015-818874.ru&img_url=1522-msk.ucoz.ru%2F_fr%2F1%2F2551801.jpg&rpt=simage&nl=1)
Конечно, скоро выдача будет несколько иной. Но пример показывает, что Я узнает рамку и разные подписи.
Где вы там рамку увидели. ) Если уж делать рамку, то толстую. Иначе всё бессмысленно.
Где вы там рамку увидели. ) Если уж делать рамку, то толстую. Иначе всё бессмысленно.
тут: http://6494876.ru/images/fotowall/nature%20099.jpg
Рамка не влияет. Если только размытая и по ширине в половину изображения.
тут: http://6494876.ru/images/fotowall/nature%20099.jpg
Рамка не влияет. Если только размытая и по ширине в половину изображения.
Не в половину. 10% будет достаточно.
ТС, просто интересно, с какой целью интересуетесь?
По теме: есть несколько способов определения т.н. "нечетких дубликатов". Под "нечетким дубликатом" я понимаю то что если взять фотку, изменить ей разрешение, немножко обрезать по краям, наложить пару водяных знаков, изменить формат с gif на jpg - то файл по структуре изменится на 100%, но визуально человек видит что это одна и та же фотка. Именно поэтому, как тут писали выше, Яндекс определяет дубликат и с водяными знаками, и с прочими преобразованиями.
Про "рамки", "зеркальное отражение" и т.д. - попробуйте реализовать сами - и поймете что "нечеткие дубликаты" такими способами не отыскать.
Как это делает конкретно Яндекс - знает только сам Яндекс. Но сами технологии - давно уже не секрет, нужно только погуглить.
P.S. В свое время мне приходила идея сделать что то типа поисковика по картинкам. Т.е. не как у Яндекса - введи ключевое слово - получи результат, а загрузи оригинал - и найди все копии или похожие картинки. Но че то не нашел в этой идее ничего коммерчески-привлекательного, хотя как сделать - примерно представляю.
исключительно по коду..
Bebs, а Вы не читали темку примерно месяц назад, если не ошибаюсь dadot создавал, он показывал очень интересный пример изображения (ноты) который Яндекс посчитал дубликатом, что здесь скажете по Вашей теории "исключительно по коду" или это как подбор коллизии при бруте md5 ?
Будет ли пагубно сказываться размещение на своем сайте картинок дублированных с других сайтов и вообще с интернета?
Да особо за это не наказывает, но вот если картинки на хорошем сайте уникальные - то и плюс в общую копилку. но а в целом про примеры наказания за дубли картинок не разу не видел, если есть у кого отрицательный опыт, отпишитесь, очень интересно и актуально
Для поиска дубликатов мы строим относительно компактные сигнатуры картинок, в основе которых распределение яркостей и цветов по площади изображения, а также некоторые другие признаки. Выбор данных для включения в сигнатуру зависит от самой картинки, в разных классах изображений отдельные виды сигнатур работают с переменным успехом. Сигнатуры укладываются в индексы сложной структуры для нечеткого поиска. В частично кластеризованном виде эти индексы удается загрузить в память.
С момента формулировки общего подхода до запуска в продакшн нам пришлось преодолеть большое количество практических проблем, которые разрешались разнообразными остроумными алгоритмами. Оказалось, что одной простой идеи — недостаточно.
Большинство известных алгоритмов по поиску дубликатов или похожих изображений основаны на поиске особых точек (feature extraction) на картинках или наборов статистических свойств изображений. Первый подход позволяет «выравнивать» и отождествлять изображения, полученные обрезанием, но требует почти квадратичной сложности вычисления, поэтому используется на ограниченных коллекциях, например, на выдаче поиска по одному запросу. Второй подход не дает достаточно хорошей разрешающей способности на больших коллекциях.
Отсюда: http://habrahabr.ru/company/yandex/blog/43141/
и http://clubs.ya.ru/company/replies.xml?item_no=14086
Работаю с графикой давно, поэтому скажу, что, кроме как по коду - фиг распознает. Или вы думаете, что там у Платона такой органический глаз и такой же органический мозг компу подключен. ИМХО, наиболее правильная идея о том, ч он берет оригинальную картинку, уменьшает, отражает, поворачивает и хранит целую пачку таких файликов, да еще и в разных палитрах и степенях сжатия. Возможно даже хранит результаты от Фотошопа, АсиДиси, Пеинта.
Большая часть картинок живет в JPEG, там исходник (Тифф или Рав, например) делется на сектора и каждый компрессируется отдельно, причем помимо сращивания сильно похожих цветов в градиенте, используется так же zip, но это уже в самом конце.
Матоды обмана: Крупный сложный (чтобы градиенты были) Вотермарк в углу (работает!)
Очень люблю фильтр "Размытие по поверхности" - полностью перелопачивает весь
код и при этом можно "вытянуть" качество, что-то вроде "гламурной ретуши", только
на автомате - идеально походит для порно.
Смена размера с последующим прогоном "РП"
А сверху и Вотермарк еще.
Короче чем больше фильтров, СЛОЖНЫХ. Тем лучше, банальной подкруткой яркости и контраста не обойтись. Это слишком просто и сто проц мониторится.
Кстати, мне еще понравилась идея с поворотом, но естественно не на 90, 180 и т.п. градусов. Как-то не думал об этом.
В итоге, если все заюзать в комплексе, то получится хорошо. В шопе можно макросы псать, но не во всех пиратских! И нужно учесть, что шоп крайне требователен к машинке, особенно, если открыть сразу много хай-рес изображений.
Можно еще зашумить, пузырьнуть да дофига там разных фильтриков.
nitrat, кино на кадры разбери :)
nitrat, кино на кадры разбери :)
хехе - точно, спс, ночь - туплю уже
Может уже кто написал готовую прогу, делающюю картинку уник?
Может уже кто написал готовую прогу, делающюю картинку уник?
Есть скрипт, который накладывает на картинку логотип, после чего рандомно режет картинку на определенное количество маленьких частей (например, 20) и с помощью html-кода склеивает их, на данный момент используется в магазине "шапок" в Liex. Данный метод создания уникальных для поисковиков картинок 100% рабочий. Чем-то похож на размножение текстов :)
ТС, просто интересно, с какой целью интересуетесь?
P.S. В свое время мне приходила идея сделать что то типа поисковика по картинкам. Т.е. не как у Яндекса - введи ключевое слово - получи результат, а загрузи оригинал - и найди все копии или похожие картинки. Но че то не нашел в этой идее ничего коммерчески-привлекательного, хотя как сделать - примерно представляю.
есть такой сервис, http://tineye.com называется:smoke:
как видим, монетизация сервиса произведена за счет рекламы google adsense (и не только)
Есть скрипт, который накладывает на картинку логотип, после чего рандомно режет картинку на определенное количество маленьких частей (например, 20) и с помощью html-кода склеивает их, на данный момент используется в магазине "шапок" в Liex. Данный метод создания уникальных для поисковиков картинок 100% рабочий. Чем-то похож на размножение текстов
Здорово! Спасибо за рабочую идею! но этот способ при массовом потреблении будет палится ПС. а вот сервис по авторандомно уникализации картинок - очень хороший и актуальный сервис, коллеги если есть такой поделитесь ссылкой.
По заявлению российского Google, в нашей стране была запущена технология мобильного поиска по изображениям Google Goggles. которая пока работает в рамках тестирования.
Поиск по изображениям отличается от традиционного поиска картинок, потому что здесь Google пытается анализировать само графическое содержимое картинки. После отсылки пользователем фотографии с мобильного устройства пользователя в дата-центр Google поисковая система пытается определить, что изображено на картинке.
1. Если Google определяет наличие текста на фотографии (фото логотипов, вывесок и пр.), то система через Переводчик Google может попробовать перевести его на любой язык, найти в поисковой базе его источник.Также текст может быть скопирован и затем использован в другом приложении;
2. Если пользователь сделал снимок визитки, Goggles постарается выявить на ней контактную информацию. В случае успешной процедуры распознавания картинки, пользователь сможет отправить письмо по указанному на визитке электронному адресу, добавить контакт в адресную книгу, позвонить по телефонному номеру, перейти по ссылке сайта, найти адрес на карте;
3. Когда Goggles удается распознать на снимке достопримечательность, велика вероятность, что пользователь получит возможность почитать о ней дополнительную информацию в интернете или найти на картах Google местоположение объекта.
4. В случае успешного распознавания произведение искусства (картины, скульптуры), пользователь также сможет получить данные с названием работы, автором и музеем, где она находится.
5. Когда Google успешное распознает на фото книгу, CD или DVD, пользователь сможет почитать о них отзывы в сети, найти с помощью Google интернет-магазины, которые продают эти товары.
В качестве забавной дополнительной возможности сервиса Goggles можно назвать способность распознавания штрих-кодов.
Только он Goggles называется :)
dmg.shark - 27.10.2011, 15:51
Пользовался программой Goggles на своем HTC и на мое удивление она неплохо работает. Пробовал распознавать денежные купюры, а так же переводить сфотографированный анг текст, с последним не особо получилось. Скачать программу можно тут http://www.google.com/mobile/goggles/#text
Ruskront - 27.10.2011, 15:53
Понедельник, 08 Августа 2016 г. 16:42 (ссылка )
Это подробная инструкция по распознаванию образов в R с использованием глубокой сверточной нейронной сети, предоставляемой пакетом MXNet. В этой статье приведен воспроизводимый пример, как получить 97,5% точность в задаче распознавания лиц на R.
Мне кажется, кое-какое предисловие все же нужно. Я пишу эту инструкцию исходя из двух соображений. Первое — предоставить всем полноценно воспроизводимый пример. Второе — дать ответы на уже возникшие ранее вопросы. Пожалуйста, примите во внимание, что это лишь мой способ подойти к решению этой проблемы, он точно не единственный и, определенно, не лучший.
ТребованияЯ собираюсь использовать и Python 3.x (для получения и предварительной обработки данных), и R (собственно, решение задачи), поэтому имеет смысл установить оба. Требования к пакетам R таковы:
Что касается Python 3.x, установите и Numpy. и Scikit-learn. Возможно, стоит также установить и дистрибутив Anaconda. в котором есть ряд предустановленных популярных пакетов для анализа данных и машинного обучения .
Как только у вас все это заработало, можно приступать.
Набор данныхЯ собираюсь использовать набор лиц Olivetti. Этот набор данных — коллекция изображений 64 на 64 пикселя, в 0-256 градациях серого.
Набор данных содержит 400 изображений 40 людей. С 10 экземплярами для каждого человека обычно используют неконтролируемые или полуконтролируемые алгоритмы, но я собираюсь постараться и использовать конкретный контролируемый метод.
Для начала нужно масштабировать изображения по шкале от 0 до 1. Это делается автоматически функцией, которую мы собираемся использовать для загрузки набора данных, поэтому не стоит об этом беспокоиться, но нужно знать, что это уже сделано. Если вы собираетесь использовать свои собственные изображения, предварительно масштабируйте их по шкале от 0 до 1 (или по -1;1, хотя первое лучше работает с нейронными сетями, исходя из моего опыта). Ниже — скрипт на Python, который нужно выполнить, чтобы загрузить набор данных. Просто измените пути на ваши значения и выполните из IDE или терминала.
Фактически, этот кусочек кода делает следующее: загружает данные, изменяет размеры картинок по Х и сохраняет массивы numpy в файл .csv.
Массив х является тензором (тензор — красивое название многомерной матрицы) размера (400, 64, 64): это означает, что массив х содержит 400 экземпляров матриц 64 на 64 (считанных изображений). Если сомневаетесь, просто выведите первые элементы тензора и попробуйте разобраться в структуре данных с учетом того, что вы уже знаете. Например, из описания набора данных мы знаем, что у нас есть 400 экземпляров, каждый из которых — изображение 64 на 64 пикселя. Мы сглаживаем тензор х до матрицы размером 400 на 4096. То есть, каждая матрица 64 на 64 (изображение) теперь конвертируется (сглаживается) в горизонтальный вектор длиной 4096.
Что касается у, то это уже вертикальный вектор размером 400. Его не нужно изменять.
Посмотрите на получившийся файл .csv и убедитесь, что все преобразования понятны.
Немного предварительной обработки в RТеперь мы воспользуемся EBImage. чтобы изменить размер изображений до 28 на 28 пикселей, и сгенерируем обучающий и тестовый наборы данных. Вы спросите, зачем я изменяю размеры изображений. По какой-то причине моему компьютеру не нравятся картинки 64 на 64 пикселя, и каждый раз при запуске модели с данными возникает ошибка. Плохо. Но терпимо, поскольку мы можем получить хорошие результаты и с меньшими картинками (но вы, конечно, можете попробовать запустить и с 64 на 64 пикселя, если у вас нет такой проблемы). Итак:
Эта часть должна быть достаточно понятна, если вы не уверены, как выглядят выходные данные, стоит взглянуть на набор данных rs_df. Это должен быть массив данных 400x785, приблизительно такой:
label, pixel1, pixel2, …, pixel784
Построение моделиТеперь самое интересное, давайте построим модель. Ниже скрипт, который был использован, чтобы обучить и протестировать модель. Ниже будут мои комментарии и пояснения к коду.
После загрузки обучающего и тестового набора данных я использую функцию data.matrix. чтобы превратить каждый набор данных в числовую матрицу. Помните, первый столбец данных — метки, связанные с каждой картинкой. Убедитесь, что вы удалили метки из train_array и test_array. После разделения меток и зависимых переменных нужно указать MXNet обработать данные. Это я делаю в строке 19 следующим кусочком кода: «dim(train_array) < — c(28, 28, 1, ncol(train_x))» для обучающего набора и в строке 24 для тестового. Таким образом мы фактически говорим модели, что обучающие данные состоят из ncol(train_x) образцов (360 картинок) размером 28x28. Число 1 указывает, что картинки в градации серого, т.е. что у них только 1 канал. Если бы картинки были в RGB, 1 нужно было бы заменить на 3, именно столько каналов имели бы картинки.
Что касается структуры модели, это вариация модели LeNet, использующей гиперболический тангенс как активационную функцию вместо «Relu» (трансформированный линейный узел), 2 сверточных слоя, 2 слоя подвыборки, 2 полностью связных слоя и стандартный многопеременный логистический вывод.
Каждый сверточный слой использует ядро 5х5 и применяется к фиксированному набору фильтров. Посмотрите это прекрасное видео. чтобы празобраться со сверточными слоями. Слои подвыборки используют классический подход «максимального объединения».
Мои тесты показали, что tanh работает гораздо лучше, чем sigmoid и Relu, но вы можете попробовать и другие функции активации, если есть желание.
Что касается гиперпараметров модели, уровень обучения немного выше обычного, но работает нормально, пока количество периодов — 480. Размер серии, равный 40, тоже хорошо работает. Эти гиперпараметры получены путем проб и ошибок. Можно было сделать поиск по перекрывающимся полосам, но не хотелось переусложнять код, так что я воспользовался проверенным методом — проб и ошибок.
В конце вы должны получить точность 0.975.
ЗаключениеВ целом, эту модель было достаточно легко настроить и запустить. При запуске на CPU обучение занимает 4-5 минут: немного долго, если вы хотите поэкспериментировать, но все же приемлемо для работы.
Учитывая тот факт, что мы никак не работали с параметрами данных и выполнили только простые и самые обычные шаги предварительной обработки, мне кажется, что полученные результаты весьма неплохи. Конечно, если бы мы хотели добиться более высокой «настоящей» точности, нужно было бы сделать больше перекрестных проверок (что неизбежно заняло бы много времени).
Спасибо, что дочитали, и надеюсь, эта статья помогла вам понять, как настраивать и запускать эту конкретную модель.
Источник набора данных — набор лиц Olivetti, созданный AT&T Laboratories Cambridge.
Воскресенье, 07 Августа 2016 г. 22:00 (ссылка )
Kaggle — это платформа для проведения конкурсов по машинному обучению. На Хабре частенько пишут про неё: 1. 2. 3. 4. и.т.д.
Конкурсы на Kaggle интересные и практичные. Первые места обычно сопровождаются неплохими призовыми (топовые конкурсы — более 100к долларов). В последнее время на Kaggle предлагали распознавать:
И многое-многое другое.
Мне давно хотелось попробовать, но что-то всё время мешало. Я разрабатывал много систем, связанных с обработкой изображений: тематика близка. Навыки более лежат в практической части и классических Computer Vision (CV) алгоритмах, чем в современных Machine Learning техниках, так что было интересно оценить свои знания на мировом уровне плюс подтянуть понимание свёрточных сетей.
И вот внезапно всё сложилось. Выпало пару недель не очень напряжённого графика. На kaggle проходил интересный конкурс по близкой тематике.Я обновил себе комп. А самое главное — подбил vasyutka и Nikkolo на то, чтобы составить компанию.
Сразу скажу, что феерических результатов мы не достигли. Но 18 место из 1.5 тысяч участников я считаю неплохим. А учитывая, что это наш первый опыт участия в kaggle, что из 3х месяц конкурса мы участвовали лишь 2.5 недели, что все результаты получены на одной единственной видеокарте — мне кажется, что мы хорошо выступили.
О чём будет эта статья? Во-первых, про саму задачу и наш метод её решения. Во-вторых, про процесс решения CV задач. Я писал достаточно много статей на хабре о машинном зрении(1 ,2 ,3 ), но писанину и теорию всегда лучше подкреплять примером. А писать статьи по какой-то коммерческой задаче по очевидным причинам нельзя. Теперь наконец расскажу про процесс. Тем более что тут он самый обычный, хорошо иллюстрирующий как задачи решаются. В-третьих, статья про то, что идёт после решения идеализированной задаче в вакууме: что будет когда задача столкнётся с реальностью.
Задача, которую мы начали делать звучала следующим образом: «Определить принадлежность водителя на фотографии к одной из десяти групп: аккуратное вождение, телефон в правой руке, телефон у правого уха, телефон в левой руке, телефон у левого уха, настройка музыки, пьёт жидкость, тянется назад, поправление причёски (красит губы, чешет затылок), разговор с соседом». Но, как мне кажется, лучше один раз посмотреть на примеры:
Всё кажется понятным и очевидным. Но это не совсем так. Какому классу принадлежат вот эти два примера?
Первый пример — 9 класс, разговор. Второй пример — первый класс, безопасное вождение.
По нашей оценке точность человека при распознавании класса по базе составляет где-то 94%. При этом наибольшую сумятицу вносит именно первый и десятый классы. На момент начала нашего участия первые места имели точность примерно на уровне 97% правильных распознаваний. Да-да! Роботы уже лучше машин!
Сегодня основным средством для решения задач такого плана являются свёрточные нейронные сети. Они производят анализ изображения на многих уровнях, самостоятельно выделяя ключевые особенности и их отношения. Прочитать про свёрточные сети можно тут. тут и тут. У свёрточных сетей есть ряд минусов:
Альтернативам свёрточных сетей может являться ручной менеджмент низкоуровневых признаков. Выделить руки. Положение лица. Выражение лица. Открытый/закрытый козырёк у машины.
Свёрточных сетей очень много разных. Классический подход — использовать наиболее распространённые сети из «Зоопарка» (caffe theano keras ). Это в первую очередь VGG16, VGG19, GoogleNet, ResNet. Для этих сетей есть много вариаций плюс можно использовать техники ускоряющие обучение. Конечно, данный подход используют все участники. Но базовый неплохой результат можно получить только на нём.
Наш сетапВсе вычисления в нашей работе проходили на одной единственной GTX1080. Это последняя игровая карта у NVIDIA. Не самый лучший вариант из того, что есть на рынке, но достаточно неплохой.
Мы хотели использовать кластер с тремя Tesla на одной из работ, но из-за ряда технических сложностей это не получилось. Так же обдумывали использование какой-то старой видеокарты из ноута на 4Gb, но в результате решили не идти по этому пути, там было сильно меньше скорости.
Используемый фреймворк — Caffe. Можно было бы использовать и Keras с Theano, что, безусловно повысило бы наш результат из-за несколько другой имплементации обучения. Но у нас не было на это времени, так что использовали по максимуму именно Caffe.
Оперативка — 16Gb, максимум при обучении использовалось 10Gb. Процессор — i5 последний.
Если вдруг кому интересно, но ничего особенного нет
Я думаю, что большая часть читателей никогда не участвовала в kaggle, так что проведу небольшой экскурс в то, какие правила у соревнования:
Предположим, что мы придумали некоторый механизм распознавания и распознали все изображения. Как они будут дальше проверяться? В данной задаче использовался подход вычисления мультиклассовых логарифмических потерь. Вкратце его можно записать как:
y — матрица решений. Единица если объект принадлежит классу.
p — матрица ответов которые прислал пользователь. Лучше всего записывать вероятность принадлежности классу.
N- число объектов
В окрестности нуля значение заменяется константой.
Мы прикинули, что вероятности «95%» соответствует значение logloss примерно «0.2», значение «0.1» соответствует вероятности «97.5%». Но это грубые оценки.
Мы ещё вернёмся к этой функции, но несколько ниже.
Первые шагиТеория хороша. Но с чего начинать? Начнём с самого простого: возьмём сетку CaffeNet, которая приложена к Caffe и для которой есть пример.
После того, как я сделал аналогичное действие — сразу получил результат «0.7786», который был где-то на 500 месте. Забавно, но у многих результат был значительно хуже. При этом, стоит отметить, что 0.77 приблизительно соответствует 80-85% правильных распознаваний.
Не будем останавливаться на этой сетке, уже достаточно устаревшей. Возьмём что-нибудь стандартное современное. К стандартным можно причислить:
Про нестандартные методы можно прочитать чуть ниже в части «Идеи, которые не прокатили».
Так как мы начинали где-то через два с половиной месяца после начала соревнования имело смысл исследовать форум. На форуме советовали VGG-16. Автор поста уверял, что получил решение с потерями «0.23» на базе данной сети.
Решение повторить у нас не удалось. Впрочем, много у кого не получилось сделать это. Хотя автор выкладывал обучающий скрипт на Keras’е. Судя по всему на Keras’е его можно было достичь, но не на caffe. Победитель, занявший третье место тоже считал VGG на Keras, а все остальные сетки на Caffe и Theano.
Нам же чистый VGG давал 0.4, что, конечно, улучшало наш результат на тот момент, но лишь места до 300ого.
В результате от VGG мы решили отказаться и опробовали обучение предобученного ResNet-50 (вот тут можно интересно почитать что это такое). Что немедленно дало нам 0.3-0.29.
Маленькая ремарка: мы так и не использовали технику «разбить базу на 8 частей». Хотя, скорее всего, она бы принесла нам небольшую дополнительную точность. Но такое обучение бы заняло несколько дней, что было нам неприемлемо.
Зачем нужно разбиение базы на 8 частей и обучение независимых сеток? Предположим, первая из сеток всегда ошибается в пользу ситуации А, при выборе из А и В. Вторая сетка наоборот — выносит решение В. При этом обе сетки часто ошибаются относительно реального решения. Но сумма сеток будет более корректно оценивать риск А/В. По сути она в большинстве спорных ситуаций поставит 50% — А, 50% — В. Такой подход минимизирует наши потери. Мы же достигали его по-другому.
Чтобы повысить точность с 0.3 мы сделали следующий ряд действий:
Изменения изображения следующие: при обучении вместо исходной обучающей картинки подаётся повёрнутая картинка, картинка подрезанная, картинка, зашумлённая помехами. Это повышает стабильность работы и повышает точность.
Итоговый результат сложения всех перечисленных сеток был на уровне «0.23-0.22».
К новым вершинамРезультат 0.22 был где-то в районе 100 места. Это уже неплохой результат. По сути тот максимум, который даёт корректно настроенная сеть. Но чтобы идти дальше нужно остановиться, подумать и осмыслить сделанное.
Самый простой способ сделать это — посмотреть «Confusion Matrix». По сути за этим понятием скрывается бюджет ошибок. Как и когда мы ошибаемся. Вот матрица, которая у нас вышла:
В этой матрице по оси x — это объекты исходного класса. По оси y — куда они были отнесены. Например, из 100% объектов нулевого класса 72% было успешно отнесено в него самого, 0.8%- в первый класс, 16.8% — в девятый.
Из матрицы можно сделать следующие выводы:
Следовательно, нужно разработать алгоритм, который более корректно может различить эти три класса.
Для того, чтобы это сделать мы воспользовались следующими идеями:
Значит, нам нужно сохранить разрешение около лица и использовать его для уточнения 0-8-9 классов. Всего у нас было три идеи как это сделать. Про две из них будет написано ниже в разделе «Идеи, которые не прокатили». Прокатила следующая идея:
Обучаем простой классификатор Хаара на выделение лица. В принципе, лицо можно даже неплохо по цвету выделить. Учитывая что мы неплохо знаем, где лицо должно оказаться.
Правила соревнований не запрещали ручную разметку тренировочной базы. Поэтому мы отметили где-то на 400 изображениях лицо. И получили весьма неплохую подборку кадров распознанную в автоматическом режиме (лица найдены корректно на 98-99% кадров):
Обучив ResNet-100 по изображениям мы получили точность где-то на уровне 80%. Но добавление результатов обучения в сумму используемых сетей дало дополнительные 0.02 по тестовой выборке переместив нас в район тридцатых мест.
Идеи, которые не прокатилиРазорвём стройную канву повествования и сделаем небольшой шаг в сторону. Без этого шага всё хорошо, а с этим шагом становиться понятно, что происходило в голове на тот момент.
Идей, которые не дают результата в любой исследовательской задаче сильно больше, чем идей, которые дают результат. А иногда случается, что идеи по тем или иным причинам нельзя использовать. Тут небольшой список идей, которые мы уже успели опробовать на момент выхода на тридцатые места.
Первая идея была простой как бревно. Мы уже писали на Хабре (1. 2 ) про сети, которые могут раскрашивать изображения по классовой принадлежности объектов. Нам показалось, что это очень хороший подход. Можно научить сеть детектировать именно то, что нужно: телефоны, руки, открытый козырёк у машины. Мы даже потратили два дня на разметку, настройку и обучения SegNet. И вдруг мы поняли, что SegNet имеет закрытую не OpenSource лицензию. А следовательно мы не можем честно его использовать. Пришлось отказаться. А результаты автоматической разметки были перспективными (здесь показано сразу несколько подходов).
А вот так выглядит процесс разметки:
Вторая идея касалась того, что разрешения 224*224 нам не хватает для принятия решения 0 класс или 9. Наибольшие проблемы доставляет потеря разрешения на лицах. Но нам было известно, что лицо практически всегда находиться в левой верхней части изображения. Поэтому мы перетянули картинки, получив таких милых головастиков с максимальным разрешением в интересных нам местах:
Не прокатило. Результат был примерно как от обычного обучения + сильно коррелированный с тем, что у нас было.
Следующая идея была достаточно большой и объемлющей. Посты на форуме конкурса натолкнули нас на размышления: а что же сеть видит в реальности? Что её интересует?
Есть целый подбор статей на эту тему: 1. 2. 3
На форуме Kaggle приводились такие классные картинки:
Мы, естественно, решили изобрести свой велосипед, для данной задачи. Тем более пишется он очень просто.
Берём исходное изображение и начинаем двигать по нему чёрный квадрат. При этом смотрим, как изменяется отклик системы.
Результат же отрисуем в качестве тепловой карты.
На изображении тут показан пример неправильной классификации изображения класса 9 (разговор с соседом). Изображение классифицировано как «тянется к контролю музыкой». И действительно, похоже. Ведь сеть сама по себе не видит 3d. Она видит руку, которая лежит в направлении к переключателю приборной панели. Ну и что что рука лежит на ноге.
Посмотрев ещё с несколько десятков ошибок мы поняли, что опять всё упирается туда же: сетка не смотрит на то, что происходит на лице.
Поэтому мы придумали другой способ обучения. На вход сети подавался набор, где половина картинок шло напрямую из обучающей базы, а половина была с затёртым всем кроме лица:
И о чудо, сетка стала на порядки лучше работать! Например по ошибочно классифицированному мужику:
Или вот, по другому (как было — как стало):
При этом сеть неплохо работала и по остальным классам (отмечала корректные зоны инереса).
Мы уже хотели праздновать победу. Загрузили сеть на проверку — хуже. Объединили с нашей лучшей — итоговый результат не улучшился. Даже не помню, стали ли мы её добавлять в наш лучший ответ. Долго думали, что у нас какая-то ошибка, но ничего не нашли.
Вроде как с одной стороны — сеть стала правильнее смотреть и много какие ошибки исправлять. С другой стороны где-то начала новые делать. Но при этом значимой статистической разницы не давала.
Идей которые не прокатили было сильно больше. Был Dropout, который нам почти ничего не дал. Были дополнительные различнае шумы: тоже не помогло. Но про это ничего красивого и не напишешь.
Вернёмся к нашим баранамМы остановились где-то в районе 30х мест. Осталось немного. Множество идей уже провалилось, на компе накопилось штук 25 тестовых проектов. Улучшений не было. Наши знания о нейронных сетях плавно начали исчерпываться. Поэтому пошли гуглить форум текущего конкурса и старые форумы kaggle. И решение нашлось. Оно называлось «pseudo labeling» и "Semi-supervised learning ". И ведёт оно на тёмную сторону. Вернее серую. Но было объявлено админами конкурса как легальное.
Вкратце: мы используем тестовую выборку для обучения разметив её алгоритмом обученным по тренировочной выборке. Звучит странно и сумбурно. Но если подумать, то оно забавно. Загоняя в сеть объекты, которые ей же размечены мы ничего не улучшаем в локальной перспективе. Но. Во-первых, мы учимся выделять те признаки, которые дают такой же результат, но проще. По-сути мы обучаем свёрточные уровни таким образом, чтобы они научились выделять новые признаки. Может на каком-то следующем изображении они выделяться и лучше помогут. Во-вторых, мы защищаем сеть от переобучения и оверфита, внося псевдо-произвольные данные, которые заведомо не ухудшат сеть.
Почему этот путь ведёт на серую сторону? Потому что формально использовать тестовую выборку для обучения запрещено. Но ведь мы тут её не используем для обучения. Только для стабилизации. Тем более админы разрешили.
Результат: + 10 позиций. Попадаем в двадцатку.
Итоговый график блуждания результатов выглядел примерно следующим образом(в начале мы не расходовали все попытки в день):
Где-то в начале статьи я упомянул про то, что к LogLoss я ещё вернусь. С ним всё не так просто. Можно заметить, что log(0) это минус бесконечность => если вдруг поставить 0 в классе где ответ единица, то мы получим минус бесконечность.
Неприятно. Но организаторы защитили нас от этого. Они говорят, что они заменяют величину стоящую под log на max(a,10^(-15)). А значит мы получаем добавку -15/N к результату. Что равно -0.000625 к результату за каждое ошибочное изображение для публичной проверки и -0.0003125 для закрытой. Десять изображений влияют на ошибку в третьем знаке. А это уже позиции.
Но ошибку можно уменьшить. Предположим, вместо 10^(-15) мы поставим 10^(-4). Тогда если мы ошибёмся мы получим -4/N. Но если мы угадаем правильно, то у нас тоже будут потери. Вместо log(1)=0 мы возьмём log(0.9999), что равно -4*10^(-5). Если мы ошибаемся раз в 10 попыток, то нам безусловно это выгоднее, чем потери 10^(-15).
А дальше начинается магия. Нам нужно объединить 6-7 результатов, чтобы оптимизировать метрику LogLoss.
Всего мы делали 80 отправок результата. Из них где-то 20-30 было посвящено именно оптимизации потерь.
Я думаю, что 5-6 мест у нас отыграно за этот счёт. Хотя, как мне кажется, все этим занимаются.
Всю эту магию делал Vasyutka. Я даже не знаю, как последний вариант выглядел. Лишь его описание, которое мы себе сохранили, достигало двух абзацев.
Что мы не сделалиНа момент окончания конкурса у нас остался небольшой стэк идей. Наверное, если бы мы всё успели, то это стоило бы нам ещё пяток позиций. Но мы понимали, что это явно не выход в топ-3, поэтому не бросали на борьбу все оставшиеся силы.
После конца конкурса многие участники публикуют свои решения. Вот тут ведётся статистика по лучшим 20 из них. Сейчас где-то половина из топ-20 опубликовала решения.
Начнём с лучшего из опубликованных. Третье место .
Скажу сразу. Решение мне не нравиться и кажется нарушением правил конкурса.
Авторы решения отметили, что все примеры снимались последовательно. Для этого они проанализировали тестовую выборку в автоматическом режиме и нашли соседние кадры. Соседние кадры — это изображения с минимальным изменением => они принадлежат одному классу => по всем близким решениям можно вынести единый ответ.
И да, это ужасно помогает. Если вы разговариваете по телефону держа его в левой руке — есть кадры где не видно телефона и непонятно, говорите вы или чешите голову. Но посмотрев на соседний кадр можно всё прояснить.
Я бы не возражал, если бы таким образом накапливалась статистика и вычиталась фоновая машина. Но реверсинженерить видео — это по мне за гранью добра и зла. Почему-объясню ниже. Но, конечно, решение за организаторами.
Мне очень нравиться пятое решение. Оно такое классное и настолько тривиальное. Мысль приходила мне в голову раз десять по ходу конкурса. Но каждый раз я отметал её. «Зачем?!». «Почему это вообще будет работать?!». «Лень тратить время на эту бесперспективщину».
Я даже не обсудил её с товарищами. Как оказалось — зря. Идея вот:
Взять две картинки одного класса. Разбить пополам и склеить. Подать в обучение. Всё.
Я не очень понимаю почему это работает (кроме того, что это стабилизирует выборку: 5 миллионов сэмплов это круто, это не 22 тыщи). А ещё у ребят было 10 карточек TitanX. Может это сыграло важную роль.
Шестое решение плохо описано, я его не понял. Девятое очень похоже на наше. Да и точность отличается не сильно. Судя по всему ребята смогли натренировать сети лучше и качественнее. Подробно они не описали за счёт чего небольшой прирост.
Десятое решение реализовало часть наших идей но чуть чуть по-другому:
Вырезать область с человеком, чтобы увеличить разрешение -> подать на обучение. Решаются те же проблемы которые мы решали вырезанием лица. Но, судя по всему, лучше.
15 решение — всё как у нас. Даже лиц так же вырезали (плюс область руля от чего мы отказались).
Но… Они натренировали 150 моделей и складывали их. 150.
19, 20 решение — всё как у нас но только без лиц. И 25 натренированных моделей.
От игрушек к делуПредположим вы страховая фирма, которая хочет внеедрить систему определения того что делает водитель. Вы собрали базу, несколько команд предложили алгоритмы. Что имеем:
Но, ещё получили несколько неплохих и интересных моделей.
Давайте пойдём дальше. И поймём насколько работают эти модели. К сожалению, их у меня нет, так что тестировать буду на нашей, которая дала 18й результат, что в принципе не так уж и плохо.
Из всех статей, которые я написал на Хабр моя любимая про то как надо собирать базу. Вот с этой стороны и подойдём к анализу. Что мы знаем о собранной базе?
На первый раз хватит четырёх ситуаций. Но их значительно больше. Все ситуации нельзя предвидеть никогда. Именно поэтому базу нужно набирать настоящую а не моделировать.
Поехали. Кадры ниже делал сам.
Как повлияло то, что при наборе базы водители не водили. Вождение, это достаточно сложный процесс. Нужно крутить головой градусов на 120, смотреть на светофоры, круто поворачивать на перекрёстках. Всего этого в базе нет. А следовательно, такие ситуации определяются как «разговор с соседом». Вот пример:
Дневные часы. Это очень большая проблема. Конечно, можно сделать систему, которая будет ночью смотреть на водителя включая ИК подсветку. Но в ИК подсветке человек выглядит совсем по другому. Нужно будет целиком переделывать алгоритм. Скорее всего тренировать один на день и один на ночь. Но есть не только проблема ночи. Вечер — когда ещё светло но уже темно для камеры и есть шумы. Сетка начинается путаться. Веса на нейронах гуляют. Первая из картинок распознана как разговор с соседом. Вторая картинка — прыгает между «тянется назад», «мэйкап» (что в рамках сети логично, ведь я тянусь к козырьку), «разговор с соседом», «безопасное вождение». Солнце на лице — очень неприятный фактор, знаете ли…
Про перфекционизм. Вот более-менее реальная ситуация:
И веса на нейронах: 0.04497785 0.00250986 0.23483475 0.05593431 0.40234038 0.01281587 0.00142132 0.00118973 0.19188504 0.0520909
Максимум на том, что телефон у левого уха. Но сеть немножко сошла сума.
Про Россию вообще молчу. Почти все кадры с рукой на ручке передач распознаны как «тянется назад»:
Видно, что проблем достаточно много.Я не стал тут добавлять снимки где я пробовал обмануть сеть (включением фонаря на телефоне, странными шапками, и.т.д.). Это реально и это обманывает сеть.
Паника. Почему всё так плохо? Вы же обещали 97%!!А проблема в том, что НИКАКАЯ система компьютерного зрения не делается с первой итерации. Всегда должен быть процесс запуска. Начиная с простого тестового образца. С набора статистики. С исправлением появляющихся проблем. А они будут всегда. При этом 90% нужно исправлять не программно, а административно. Попался на том, что пробовал обмануть систему — получи пирожок. Кто-то не так крепит камеру? Будь добр, крепи по человечески. А не то сам дурак.
Делая разработку нужно быть готовым, что прежде чем получиться идеальный результат нужно будет всё 2-3 раза переделать.
И мне кажется, что для данной задачи всё не плохо, а наоборот, хорошо. Показанные 95-97% работоспособности по тесту хороши и означают, что система перспективна. Это значит, что итоговую систему можно будет довести до плюс-минус такой же точности. Просто нужно вложить в разработку ещё в 2-3 раза больше сил:)
Кстати. Про крепление камеры. судя по всему, то как крепили камеру набирая статистику мешает пассажиру. То, как крепил камеру я — даёт немножко другую картинку, по которой падает статистика. Зато не мешает пассажиру. Думаю, что решение с камерой мешающей пассажиру будет непригодно, скорее всего будут пересобирать базу. Или сильно дособирать.
Так же не понятно где планируются обрабатываться изображения. В модуле, который будет снимать? Тогда нужно там иметь прилично вычислительной мощи. Отправлять на сервер? Тогда это явно единичные кадры. Сохранять на карте и раз в неделю передавать с домашнего компа? Неудобный форм-фактор.
Сколько же время уходит на задачу такого плана с нуляДохрена. Я ни разу не видел задачу доведённую до релиза быстрее чем за пол года. Наверное, приложения вида Prism, конечно, можно и за месяц развернуть, а то и быстрее, если инфраструктура есть. Но любая задача где важен результат и которая не является арт-проектом — это долго.
Конкретно по этой задаче. В наборе базы было задействовано минимум человек 70. Из которых человек 5 минимум — обслуживающий персонал, который водил грузовик, сидел с блокнотиком. А человек 65-100 — люди которые вошли в базу (не знаю, сколько их всего). Организовать такую движуху, все набрать-проверить вышло у организаторов вряд ли меньше, чем 1-2 месяца. Сам конкурс шёл 3 месяца, но сделать неплохое решение по набранной базе можно и за 2-3 недели (что мы и сделали). А вот довести это решение до рабочего образца может выйти уже в 1-3 месяца. Нужно оптимизировать решение под железо, выстраивать алгоритмы передачи, дорабатывать решение чтобы оно в холостую при отсутствии водителя ничего не гоняло. И прочее-прочее-прочее. Такие вещи всегда зависят от постановки задачи и от того где и как решение должно использоваться.
А потом начинается второй этап: опытная эксплуатация. Нужно поставить систему людям 40-50 в машину на пару дней каждому и посмотреть как оно работает. Сделать выводы когда оно не работает, обобщить и переработать систему. И тут начнётся болото, где оценить сроки реализации априори до начала работ практически невозможно. Нужно будет принимать правильные решения: в каких ситуациях система дорабатывается, в каких ставиться заглушка, а в каких мы будем бороться административно. Это самое сложное, это мало кто умеет.
Выводы будут на тему kaggle. Мне понравилось. Я порадовался нашему уровню. Периодически мне казалось, что мы отстали от времени, выбираем не оптимальные методы в нашей работе. А походу всё норм. Со стороны оценки себя в окружающем мире kaggle очень хорош.
Со стороны решения задач kaggle интересный инструмент. Наверное это один из правильных и всеобъемлющих методов, который позволяет провести неплохой НИР. Нужно только понимать, что готовым продуктом тут не пахнет. Но понять и оценить сложность и пути решения задачи — нормально.
Будем ли мы участвовать ещё — не знаю. Сил чтобы бороться за первые места нужно потратить массу. Но, если будет интересная задачка — почему бы и нет.
Пятница, 01 Апреля 2016 г. 19:49 (ссылка )
Распознавание изображений — одна из задач, с которой лучше всего справляются сервисы с элементами искусственного интеллекта. Корпорация IBM запустила в тестовом режиме проект, который позволяет любому пользователю проверить возможности когнитивной системы Watson касательно распознавания изображений.
Сервис работает с фотографиями или картинками (можно загружать свои файлы, указывать адрес картинки в Сети или попробовать поработать с фотографией, представленной компанией). Если распознавание прошло успешно, система укажет список объектов, предположительно изображенных на картинке или фото, а также покажет вероятность каждого предположения. При желании можно создать собственную категорию объектов (уточнить существующую категорию, либо создать новую).
Обычно распознавание изображений работает в полуавтоматическом режиме — на картинке выделяются определенные объекты, которые уже должен идентифицировать пользователь. Но сервис IBM (доступен по ссылке ) самостоятельно выполняет такую работу, используя семантические классификаторы, создаваемые самой системой и вводимые разработчиками в процессе обучения. Распознавать когнитивная система может не только объекты, но и события или условия среды, при помощи таких характеристик, как цвет, текстура, форма или края изображения.
В работе сервис использует также платформу IBM Multimedia Analysis and Retrieval System (IMARS ). Это дает возможность разработчикам обучать Watson, а также создавать приложения для своих нужд на основе возможностей когнитивной системы. Например, ритейлер может создавать тег, классификатор, имеющий отношение к его одежде (брюки определенной марки). И тогда при необходимости сервис может идентифицировать такую одежду, если фотография с ней появляется в сети. То есть продавец (или производитель) одежды может видеть, насколько популярен его товар среди пользователей Сети.
Кстати, сервис уже работает в тестовом режиме в интересах компании MP Maritime (доставка грузов морем). При помощи ресурсов IBM эта компания получает возможность отслеживать крупные грузовые корабли на спутниковых снимках. Возможности сервиса можно опробовать в среде Watson Developer Cloud на Bluemix.
Паспортный сканер своими рукамиВторник, 01 Марта 2016 г. 12:14 (ссылка )
Привет, Хабр! В предыдущих статьях мы уже рассказывали вам про то, как нам удалось превратить ввод паспортных данных на мобильных устройствах из рутины в простую и быструю процедуру. Следующим закономерным шагом мы превратили наш Smart PassportReader SDK в серверную компоненту, облегчив тем самым крупным финансовым организациям работу с документами в бэк-офисах. Наконец, проявив изобретательскую смекалку и инженерный подход, нам удалось разработать программно-аппаратный комплекс (забегая вперед, представим его название — Smart PassportBox ), позволяющий оптимизировать работу фронт-офисов и СКУД-решения. Поэтому, если вам интересно сколько директоров, программистов, паяльников, лобзиков и отверток требуется для создания полноценного ПАК, добро пожаловать под кат.
Сразу хочется внести ясность — мы не заявляем, что изобрели колесо. Первые автоматизированные рабочие места по распознаванию паспортов РФ появились более 10 лет назад (программное обеспечение для решения поставленной задачи есть как у известных гигантов в области распознавания документов — Abbyy и Cognitive, так и у сравнительно небольших фирм — например, PassportVision).
На первый взгляд кажется, что такая простая и понятная задача решена. Бери и пользуйся. Однако, при более детальном рассмотрении возникает ряд ограничений, с которыми сталкиваешься при интеграции. Разберем две основные проблемы.
Во-первых, как бы печально это ни звучало, большинство распознающего софта работает только на ПК под управлением MS Windows. Однако, в последние годы в связи с активным развитием сообществ открытого программного обеспечения все чаще на рабочих станциях операторов можно увидеть Linux. Следовательно, распознающий паспорта софт также должен следовать этому тренду.
Во-вторых, для качественного распознавания паспортов требуется сканер (надо как-то получить графический образ документа). И тут потребитель обычно стоит перед выбором: дешево, долго, со средним качеством либо дорого, быстро и с кучей дополнительных “примочек”. Поясним сложившуюся проблему чуть подробнее. На сегодняшний день принято получать изображение документа одним из двух путей: с помощью планшетного сканера или с помощью специального паспортного устройства. Планшетные сканеры при своей относительной дешевизне (цена на компактные модели размера A5 стартует примерно с 12 000 рублей) позволяют получить пригодную для распознавания картинку за 10-15 секунд. При этом не факт, что распознавание будет выполнено с первого раза и не потребуется повторного сканирования (из-за загиба страницы или неправильной ориентации документа). За это время опытная машинистка может вбить паспортные данные вручную. Ускорить процесс можно с помощью специализированных устройств (обычно, позволяющих помимо мгновенного сканирования выполнять верификацию, распознавание информации на встроенном чипе и т.п.), основным минусом которых является стоимость (порядка 100 000 рублей).
Проведя анализ, мы поняли, что рынок недорогих, но эффективных решений распознавания паспортов еще не разработан полностью, еще есть место для новых инженерных и наукоемких решений.
Так мы мы вдохновились на создание программно-аппаратныого комплекса…
Разработка оптического сканирующего устройстваКак вы уже наверное поняли из введения, оптическое устройство — основополагающая часть всего программно-аппаратного комплекса. Поэтому мы щедро выделили на это устройство 100 долларов, не уменьшая при этом требований к качеству и скорости получения изображений. Первое (и самое очевидное), что пришло в голову — использование хорошей web-камеры. Тем более распознавать видео мы умеем хорошо (читайте наш предыдущий пост ). И да, Хабр, у нас получилось достаточно успешно! Комбинация web-камера + Smart PassportReader позволяет решить задачу автоматизированного ввода документов. Правда, освоить работу с таким ПАК рядовому оператору оказалось не так просто по следующим причинам:
Немного поразмыслив, мы решили установить камеру внутрь замкнутого ящика со стеклянной “крышкой”, про который известно все: расстояние от камеры до документа (можно фиксировать фокусное расстояние), параметры освещения всегда одинаковы и не зависят от внешних факторов, паспорт прижимается к стеклянной поверхности, что позволяет легко избежать эффекта книжки.
За длинные холодные зимние каникулы, вооружившись досками и отвертками вместо сноубордов и лыж, мы начали творить устройство… Из дерева…
Несмотря на кажущуюся простоту, получившееся устройство обладает своими нюансами:
В результате, с третьей попытки (еще раз спасибо руководству страны за такие продолжительные каникулы) нам удалось собрать сканер-ящик, возвращающий хоть и проективно-искаженные, но вполне пригодные для распознавания с помощью нашего SDK видеопоследовательности.
Ниже представлена краткая смета стройматериалов, которые пошли на изготовление. Как видите, в заветные 100 долларов мы уложились с запасом.
Разработка программного обеспеченияЕсли создание коробки для нашей организации (которая по роду деятельности занимается разработкой софта) — это своего рода вызов, то подготовка распознающей программы на базе собственно нашего SDK — это фактически отдых. Итак, в соответствии с нашей целью, распознающий софт должен отвечать следующим требованиями:
Соответственно, при разработке софта мы использовали следующие приемы:
Следуя поговорке “Лучше один раз увидеть…” мы решили снять небольшой ролик про получившийся программно-аппаратный комплекс.
Рубрика “Вопросы и Ответы”В этом разделе мы набрались смелости чтобы предсказать ваши вопросы и заранее сформулировать на них ответы. Однако, мы с нетерпением ждем других вопросов в комментариях к статье.
1. Так все-таки, сколько директоров, программистов и инструментов потребовалось для создания такого ПАК?
Все столярные материалы можно купить в крупном строительном магазине (в нашем случае — Леруа Мерлен), там же можно аккуратно напилить доски требуемого размера (чтобы не возиться с лобзиком дома), web-камеру — в магазине электроники типа Юлмарт, провода и светодиоды — Чип и Дип. Дополнительно потребовался 1 директор (оказалось, что директора по своей природе неплохо владеют отверткой и паяльником) и 1 программист C++ (для создания программной связки между web-камерой, Smart PassportReader SDK и интерфейсом вывода результатов).
2. Судя по изображениям ПАК имеет внушительные физические размеры. Разве с ним удобно работать?
На многочисленных демонстрациях потенциальных заказчиков действительно немного смущает высота сканера (а она сейчас 276 мм). Но надо понимать, что это всего лишь опытный образец, выполненный полностью из бытовых деталей. Если изготовить пластиковый корпус, использовать малоформатную широкоугольную камеру, то высоту устройства можно довести до 120 мм, что вполне сравнимо с существующими устройствами сканирования паспортов. Но даже при таких “громадных” размерах устройство может быть эффективно использовано: никто не запрещает спрятать этот “ящик” внутрь стола или привинтить сбоку (как показано на рисунке ниже).
3. Все равно даже при таком компактном исполнении внутри “ящика” много свободного места. Вы не думали, чем можно его заполнить?
Мы не просто думали, а уже даже приступили к заполнению “ящика”. Оставшееся место можно эффективно использовать для расположения внутри микрокомпьютера, который собственно и будет заниматься распознаванием документов (благо наш SDK отлично оптимизирован под платформу ARM). В таком виде ПАК распознавания паспортов будет локализован внутри одного устройства, не используя никакие внешние вычислительные мощности.
Конечно, нашу деревянную коробку трудно назвать готовым промышленным образцом. Тем не менее, уже на текущемй этапе нашей опытно-конструкторской разработки можно сформулировать основные преимущества получившегося программно-аппаратного комплекса, решающего задачу распознавания паспортов граждан РФ:
P.S. Концепция программно-аппаратного комплекса, описанного в данной статье, защищена патентным законодательством РФ.
[Из песочницы] Бот для сапера с изюминкойЧетверг, 17 Сентября 2015 г. 12:29 (ссылка )
Наверное у многих такое бывает: на работе нечего делать, или нужно подумать перед выполнением очередной задачи, да или попросту нет ничего вкусненького к чаю, тогда рука автоматически тянется к мышке и начинает играть в сапера. И вот в порыве очередного приступа саперомании меня посетила мысль о том, что я уже не думаю, как раньше, где расположены мины, а просто на автомате по выработанному алгоритму тычу по полю, ломая мышку. А раз я действую по алгоритму, без особых творческих усилий, то можно написать бота, который будет играть вместо меня, наверняка внимательнее и быстрее.
Таким образом, вместо того чтобы самому играть в сапера в свободное время, я решил обучить игре бота — написать программу на С#, которая будет выполнять следующее:
1) по картинке окна с игрой заполнять матрицу размеров 16*30(размеры поля сапера в профессиональном режиме) числами в соответствии с диспозицией на экране;
2) прогонять эту матрицу через алгоритм, выполняющий шаблонные действия;
3) в ходе алгоритма тыкать по полю мышкой, расставляя флаги и открывая поле, и возвращаться к первому пункту.
4) поскольку за счет третьего пункта мышь занята, то для остановки программы необходимо настроить перехват нажатых клавиш в операционной системе(т.к. активным постоянно является окно сапера, а не наша программа).
5)Осилив четыре предыдущих пункта, я решил добавить изюминку — сделать программу хоть немного более
полезной/юзабельной — сделать из нее заставку, т.е. автоматически запускать игру в сапера при бездействии клавиатуры и мыши по истечении времени, указанного пользователем(по желанию пользователя, разумеется).
Программа писалась и тестировалась для классического сапера, который был в версиях Windows до XP включительно. Далее я решил перенести ее также и на MineSweeper — сапер из Windows7, об этом в конце статьи.
Итак, пойдем по порядку.
1) В первом пункте мы создаем глаза нашего бота. Получить картинку с игрой нам поможет следующий код:
На выходе мы получили цветное изображение окна с игрой — теперь наш бот видит то же, что и мы, но пока не знает, что с этим делать, глупый. Теперь нам по картинке надо заполнить матрицу 16*30 числами от -1 до 10(-1 — это флажок, выставляемый правой клавишей, 0 — клетка не касается ни одной мины, 1-8 — количество мин-соседей у данной клетки, 9 — неоткрытая клетка, 10 — мина(появляется при подрыве)). То есть в начале каждой игры матрица должна быть заполнена девятками, а при проигрыше должна появиться хоть одна десятка. Для заполнения матрицы я сперва хотел воспользоваться какой нибудь библиотекой распознавания символов, но потом подумал, что это как стрелять из пушки по воробьям, ведь у нас всего 12 вариантов изображений, решил написать собственный модуль для распознавания. Когда я переносил приложение под сапера из Windows 7, то пожалел о своем решении, так как количество изображений возросло, и метод их отличия друг от друга заметно усложнился.
Распознать изображение и заполнить матрицу нам поможет оболочка известной библиотеки OpenCV для C# EmguCV. она очень проста в подключении и
использовании. Распознавание в приложении происходит следующим образом: из большого изображения с окном игры, полученного на предыдущем этапе, по очереди вырезаются маленькие изображения — ячейки и сравниваются с заранее заготовленными эталонами. Для более эффективного сравнения делаем изображения черно-белыми: если интенсивность серого в конкретном пикселе меньше THRESHOLD, то он окрашивается в белый, иначе в черный, далее идет попиксельное сравнение.
2) Теперь наш бот может видеть, надо научить его думать; алгоритм игры — мозг нашего бота, он состоит из нескольких частей.
Для удобства использования нашей таблицы с числами в алгоритмах прохождения игры создадим класс SaperCell, в котором помимо типа ячейки и координат зададим еще несколько свойств:
Первая часть алгоритма — самая простая, в ней мы пробегаем по всем открытым клеткам(по цифрам от 1 до 8) и проверяем, равно ли количество неоткрытых соседей данной клетки количеству мин, которых она должна касаться(типу данной клетки). Если это так, то мы знаем, что мины расположены во всех соседних неоткрытых ячейках. После этой части алгоритма обработаются все следующие ситуации:
Вторая часть алгоритма отлавливает все типичные ситуации, которые выработались у меня за время, когда не было ничего вкусненького к чаю. Таких шаблонов несколько:
1) Тройка 1, 2, 1 — в этом случае мины стоят напротив единиц.
2) Четверка 1, 2, 2, 1 — в этом случае мины стоят напротив двоек.
3) Замкнутая тройка 1, 1, 1 (это значит, что по диагонали от крайних единиц нет неоткрытых клеток, т.е. напротив тройки ровно три неоткрытых клетки) — в этом случае мина напротив центральной единицы.
4) Замкнутая четверка 1, 1, 1, 1 — мины напротив крайних единиц.
Третья часть алгоритма (если это так можно назвать): пробегаем по всем клеткам, которые уже касаются нужного количества мин, и тыкаем одновременно левой и правой кнопками мыши.
Четвертая часть алгоритма — умный клик, если предыдущие алгоритмы больше не дают результата(не раскрывают ничего нового), то идет поиск клеток, где точно нет мин: если множество неоткрытых соседей клетки А является подмножеством неоткрытых соседей клетки В, и клетка В не должна касаться большего числа мин, чем клетка А, то можно смело открывать всех неоткрытых соседей клетки В, не являющихся соседями клетки А.
Далее, аналогичным образом, идет поиск клеток, где точно есть мина.
3) Теперь наш бот знает, где точно есть мины и где их точно нет, а ничего поделать не может, как говорится нет ручек — нет конфеток. Приделаем нашему боту руки: вот код, позволяющий совершать левый клик мышью в нужной клетке окна сапера:
Теперь в ходе алгоритма, чтобы кликнуть по ячейке с координатами (x,y) достаточно написать:
Здесь mouse — это класс, содержащий все виды кликов, позволяющий проще манипулировать мышью в ходе игры.
4) После предыдущих пунктов наш бот просто неудержим — готов играть в сапера до посинения, занимая мышку. Поэтому нужно приделать ему уши, чтоб он слышал, когда останавливаться. Поскольку мышь занята, то для остановки программы придется использовать… клавиатуру, что же еще. Но и с этим есть проблема, так как активным постоянно является окно сапера, то придется отлавливать все нажатые клавиши в операционной системе. Поискав в интернетах, я набрел вот на это готовое решение. Остается создать два отдельных потока — в одном будет трудиться наш бот, во втором перехватчик нажатых клавиш, а также механизм их взаимодействия.
В функции KeyboardHook при нажатии клавиши:
В функции SaperGame:
Поток saper при игре постоянно проверяет, переменную isPaused, если она равна true(значит была нажата клавиша), то поток тормозит и ждет отмашки от ивент вайт хэндлера, а он ее дает только при повторном нажатии клавиши.
5) Теперь наш бот не только хорошо играет, но и стал очень послушным. После всяких оптимизаций (рекорд бота 5 секунд) я уже не знал, что бы еще с ним сделать, а хотелось добавить какую-то изюминку, уж очень меня это увлекло.
В итоге решил преобразовать свою программу в заставку, чего компьютеру простаивать, пусть лучше в сапера играет. Для Windows XP это сделать очень просто — изменить расширение экзешника на .scr и положить его со всеми необходимыми файлами в C\\WINDOWS\\system32, тогда он появится среди остальных стандартных заставок, остается просто выбрать интервал и программа сама запустится при бездействии компьютера. Но я решил сделать универсальное решение, чтобы можно было использовать приложение и в семерке. Для этого создал оконное приложение, висящее в трее, с возможностью добавления в автозагрузку(ведь заставка Windows работает с самого начала), а также прикрутил вот этот класс для отслеживания перемещений мыши. Теперь при любой активности мыши или клавиатуры перезапускается таймер и, если засеченное время больше заданного интервала, то стартует игра. Конечно, это не заставка из Windows, здесь отслеживаются лишь клавиатура и мышь, но все же я остался доволен.
Теперь скажу немного об обучении бота играть в Minesweeper из Windows7. Когда программа работала как часы под Windows XP, но я думал, что всего пару штришков — и все заработает под Windows7. Но не тут то было, хотя, по сути, переделать нужно было только процесс распознавания, но это потребовало времени почти столько же, сколько написание всего предыдущего кода. Дело в том, что однотипные ячейки в сапере из Windows7 очень сильно отличаются в разных частях поля. Поэтому для каждого типа ячейки пришлось заготовить сразу несколько эталонов, но и это не избавило от ошибок в распознавании, так как установить один и тот же THRESHOLD для такого количества картинок не удавалось. Поэтому пришлось для каждой ячейки на ходу высчитывать THRESHOLD, как среднюю интенсивность серого всей картинки, за счет этого время распозвнавания увеличилось в два раза. Ну ладно, главное надежно, но и после этого периодически проскакивали косяки, причем при пошаговой отладке их не было. Все дело оказалось в плавном обновлении самого окна сапера в Windows7, пришлось делать искусственные паузы перед каждым снимком экрана. Кажется все просто, но пока я дошел до этого, я проклял, что взялся за допиливание проги под MineSweeper-а, что начал изобретать этот хромающий велосипед с распознаванием. Но, благо, после небольшой оптимизации прога начала раскладывать сапера за приемлимое время и почти не сбиваться.
Исходный код программы доступен на github .
Таким вот образом у меня получилось написать довольно-таки интересное приложение, попрактиковать свои навыки программирования и изучить что-то новое. Всем, кто прочитал — спасибо, а кто скачал и попробывал бота в действии — огромная благодарность!
Четверг, 13 Августа 2015 г. 13:52 (ссылка )
На хабре уже есть множество статей, посвященных распознаванию образов методами обучения машин, таких как нейронные сети, машины опорных векторов, случайные деревья. Все они требуют значительного количества примеров для обучения и настройки параметров. Создание обучающей и тестовой баз изображений адекватного объема для них — весьма нетривиальная задача. Причем речь идет не о технических трудностях сбора и хранения миллиона изображений, а об извечной ситуации, когда на первом этапе разработки системы у вас есть полторы картинки. Кроме того, следует понимать, что состав обучающей базы может влиять на качество получающейся системы распознавания больше, чем все остальные факторы. Несмотря на это, в большинстве статей этот немаловажный этап разработки полностью опущен.
Если вам интересно узнать про все это — добро пожаловать под кат.
Перед созданием базы примеров изображений и обучением нейронной сети необходимо конкретизировать техническую задачу. Понятно, что распознавание рукописного текста, эмоций человеческого лица или определение местоположения по фотографии — совершенно различные задачи. Также ясно, что на архитектуру используемой нейронной сети повлияет выбор платформы: в “облаке”, на ПК, на мобильном устройстве — доступные вычислительные ресурсы различаются на порядки.
Дальше становится интереснее. Распознавание изображений, полученных с фотокамер высокого разрешения, или размытых изображений с веб камеры без автофокуса потребуют совершенно различных данных для обучения, тестирования и валидации. Об этом нам намекают “теоремы об отсутствии бесплатных данных”. Именно поэтому свободно распространяемые обучающие базы изображений (например, [1. 2. 3 ]), отлично подходят для академических исследований, но почти всегда неприменимы в реальных задачах вследствие своей «обобщенности».
Чем точнее обучающая выборка аппроксимирует генеральную совокупность изображений, которые будут поступать на вход вашей системе, тем выше будет предельно достижимое качество результата. Получается, что правильно составленная обучающая выборка — это и есть предельно конкретизированное техническое задание! Например, если мы хотим распознавать печатные символы на фотографии, сделанной мобильным устройством, то база примеров должна содержать фотографии документов из разных источников с различным освещением, сделанные с разных моделей телефонов и камер. Все это усложняет сбор необходимого числа примеров для обучения распознавателя.
Рассмотрим теперь несколько возможных способов подготовки выборки изображений для создания системы распознавания.
Создание обучающих примеров из естественных изображений.Примеры для обучения из естественных изображений создаются на основе реальных данных. Их создание состоит из следующих этапов:
Эти операции требуют значительных затрат рабочего времени, и, соответственно, подобный способ создания обучающий базы весьма дорог. К тому же собирать данные необходимо в различных условиях — освещение, модели телефонов, камер, с которых происходит съемка, различные источники документов (типографии), и т. д.
Все это усложняет сбор необходимого числа примеров для обучения распознавателя. С другой стороны, по результатам обучения системы на таких данных можно судить об её эффективности в реальных условиях.
Создание обучающих примеров из искусственных изображений.Другой подход к созданию обучающих данных — их искусственная генерация. Можно взять несколько шаблонов / «идеальных» примеров (например, наборов шрифтов) и с помощью различных искажений создать необходимое число примеров для обучения. Можно использовать следующие искажения:
Примеры искажений изображений для задачи распознавания символов:
Дополнительные линии на изображениях:
Сжатия и растяжения вдоль осей:
Генерировать искажения можно с помощью библиотек для работы с изображениями [1. 2. 3 ] или специальных программ, которые позволяют создавать целые искусственные документы или объекты.
Такой подход не требует большого количества человеческих ресурсов и сравнительно дешев, поскольку не требует разметки и сбора данных — весь процесс создания базы изображений определяется выбором алгоритма и параметров.
Главным минусом подобного метода является слабая связь качества работы системы на сгенерированных данных с качеством работы в реальных условиях. Кроме того, метод требует больших вычислительных мощностей для создания необходимого числа примеров. Выбор искажений, используемых при создания базы для конкретной задачи, также составляет определенную сложность.
Ниже приведен пример создания полностью искусственной базы.
Первоначальный набор изображений символов шрифта:
Примеры изображений без искажений:
Добавление небольших искажений:
Логичным продолжением предыдущего метода является генерация искусственных примеров с использованием реальных данных вместо шаблонов и первоначальных «идеальных» примеров. Добавляя искажения, можно добиться существенного улучшения работы системы распознавания. Для того чтобы понять, какие именно искажения следует применять, часть реальных данных стоит использовать для валидации. По ним можно оценивать наиболее часто встречающиеся типы ошибок и добавлять изображения с соответствующими искажениями в обучающую базу.
Такой способ создания обучающих примеров содержит в себе преимущества обоих вышеизложенных подходов: он не требует высоких материальных затрат и позволяет создать большое число примеров, необходимых для обучения распознавателя.
Сложности может вызвать аккуратный подбор параметров «раздутия» обучающей выборки из первоначальных примеров. С одной стороны число примеров должно быть достаточным для того, чтобы нейронная сеть научилась распознавать даже зашумленные примеры, с другой стороны — необходимо, чтобы при этом не падало качество на других типах сложных изображений
Сравнение качества обучения нейронной сети на примерах из естественных изображений, полностью искусственных и сгенерированных с использованием естественных.Попробуем создать нейронную сеть на изображениях символов MRZ. Машинно-читаемой зоной (MRZ — Machine-Readable Zone) называют часть документа, удостоверяющего личность, выполненную согласно международным рекомендациям, закрепленным в документе Doc 9303 — Machine Readable Travel Documents Международной Организации Гражданской Авиации. Подробнее про проблемы распознавания MRZ можно прочитать в другой нашей статье .
MRZ содержит 88 символов. Будем использовать 2 характеристики качества работы системы:
В дальнейшем нейронную сеть предполагается использовать на мобильных устройствах, где вычислительные мощности ограничены, поэтому используемые сетки будут иметь относительно небольшое число слоев и весов.
Для экспериментов было собрано 800'000 примеров символов, которые были разбиты на 3 группы: 200'000 примеров на обучение, 300'000 примеров на валидацию и 300'000 примеров на тестирование. Подобное разбиение неестественно, поскольку большая часть примеров “пропадает впустую” (валидация и тестирование), но позволяет наилучшим образом показать преимущества и недостатки различных методов.
Для тестовой выборки распределение примеров различных классов близко к реальному и выглядит следующим образом:
Название класса (символ): число примеров
0: 22416 1: 17602 2: 13746 3: 8115 4: 8587 5: 9383 6: 8697 7: 8082 8: 9734 9: 8847
<: 110438 A: 12022 B: 1834 C: 3891 D: 2952 E: 7349 F: 3282 G: 2169 H: 3309 I: 6737
J: 934 K: 2702 L: 4989 M: 6244 N: 7897 O: 4515 P: 4944 Q: 109 R: 7717 S: 5499 T: 3730
U: 4224 V: 3117 W: 744 X: 331 Y: 1834 Z: 1246
При обучении только на естественных примерах средняя посимвольная величина ошибки по 25 экспериментам составила 0,25%, т.е. общее число неправильно распознанных символов составило 750 изображений из 300000. Для практического применения подобное качество неприемлемо, поскольку число правильно распознанных зон в таком случае составляет 80%.
Рассмотрим наиболее частые типы ошибок, которые совершает нейронная сеть.
Примеры неправильно распознанных изображений:
Можно выделить следующие типы ошибок:
Таблица наиболее частых ошибок:
(формат Оригинальный символ, число ошибок, с какими символами сеть чаще всего путает данный символ и сколько раз)
Оригинальный символ: ’0’, число ошибок: 437
’O’: 419, ’U’: 5, ’J’: 4, ’2’: 2, ’1’: 1
Оригинальный символ: ’<’, число ошибок: 71
’2’: 29, ’K’: 6, ’P’: 6, ’4’: 4, ’6’: 4
Оригинальный символ: ’8’, число ошибок: 35
’B’: 10, ’6’: 10, ’D’: 4, ’E’: 2, ’M’: 2
Оригинальный символ: ’O’, число ошибок: 20
Оригинальный символ: ’4’, число ошибок: 19
Оригинальный символ: ’6’, число ошибок: 18
’G’: 4, ’S’: 4, ’D’: 3, ’O’: 2, ’4’: 2
Оригинальный символ: ’1’, число ошибок: 17
’T’: 6, ’Y’: 5, ’7’: 2, ’3’: 1, ’6’: 1
Оригинальный символ: ’L’, число ошибок: 14
Оригинальный символ: ’M’, число ошибок: 14
’H’: 7, ’P’: 5, ’3’: 1, ’N’: 1
Оригинальный символ: ’E’, число ошибок: 14
’C’: 5, ’I’: 3, ’B’: 2, ’F’: 2, ’A’: 1
Будем постепенно добавлять различные виды искажений, соответствующие наиболее распространенным типам ошибок, в обучающую выборку. Число добавленных «искаженных» изображений необходимо варьировать и подбирать, основываясь на обратном отклике валидационной выборки.
Действуем по следующей схеме:
Например, для данной задачи было сделано следующее:
Подобные “итерации” можно проводить многократно — до достижения необходимого качества или до тех пор, пока качество не перестает расти.
Таким способом, было получено качество распознавания в 94,5% правильно распознанных зон. Используя постобработку (марковские модели, конечные автоматы, N-граммные и словарные методы и т.д.), можно получить дальнейшее увеличения качества.
При использовании обучения только на искусственных данных в рассматриваемой задаче удалось достичь только качества в 81,72% правильно распознанных зон, при этом основная проблема — сложность подбора параметров искажений.
Тип данных для обучения
Процент правильно распознанных MRZ
Введение Обзор задачиИтак мы имеем такую капчу:
Впрочем многое можно исправить тонко настроив скрипт, но скажу честно, при желании и должном числе примеров, любая понятная [и не только] человеку капча поддается распознаванию.
РешениеРаспознавание текста, в большинстве случаев, можно условно разделить на следующие этапы:
Но в этот раз мы сделаем исключение, ведь большинство — не все.
Предварительная обработкаПо цвету первого пикселя убираем фон:
Нормализуем входные данные:
Никакой локации и сегментации текста не предусмотрено.
Имея должное число примеров мы просто отказываемся от этих этапов и переходим к самому интересному.
РаспознаваниеДля распознавания используется двухслойный персептрон.
Сеть обучалась попримерно (online), методом обратного распространения ошибки, с отказом от обучения на распознаваемых с требуемой точностью примерах.
Размер изображений поступающих на вход 100*50=5000 пикселей.
Первый слой обучаемый и состоит из 2000 нейронов.
Каждому нейрону выходного слоя соответствует буква/цифра на картинке, всего 6 символов по 23 варианта итого: 6*23=138 нейронов.
Обучающая и тестовая выборка составила 140,000 и 10,000 капч соответственно.
ИтогиПосле ночи обучения, точность распознавания каждого символа, на тестовой выборке, составила 61.4%, верно распознанных капч — 7.2% .
Мне этого оказалось более чем достаточно и обучение было остановлено.
Дальнейшего роста точности можно достичь предварительной обработкой изображения (даже простой отсев шумов наверняка будет иметь результат), дообучением, увеличением количества примеров (инвариантность по обучению) и изменением архитектуры (структурная инвариантность), в последнем случае я бы рекомендовал обратить внимание на Space Displacement Neural Network .
ИсходникиЕсли желаете протестировать или разобраться в работе сети — добро пожаловать на GitHub .