Распознавание картинки – распознавание одежды на фотографии с помощью мобильного приложения / Блог компании Anetika / Хабрахабр

Содержание

Удобная функция распознавания картинок с Google search by image

С недавнего времени самый массовый поисковик  предоставляет интересную возможность “поиск по картинке” – Google search by image.  По сути это распознавание изображения или как ещё называют распознавание по картинке). В чём суть сервиса?  Предположим Вы не знаете кто это такой:

Не беда, Google image подскажет! Открываем страничку Google image:

И в правом углу строки поиска видим иконку фотоаппарата (для настройки в Opera читайте ниже). Нажимаем и в появившемся меню либо вводим адрес картинки, либо загружаем её, если картинка сохранена у Вас на диске.

После поиска Google выдаёт ответ на вопрос “кто же на изображении?”: “арнольд шварценеггер”

Если Вы уберёте в левой части строки поиска параметр JPG (показано стрелкой), то поисковик выдаст более широкий перечень подходящих изображений, но теперь уже критерием поиска будет не изображение, а поисковая фраза ” арнольд шварценеггер “: 

Данной функцией можно воспользоваться и при поиске в  Google по картинке. Например Вас заинтересовало какое-то изображение:

Жмёте и переходите на страницу, на которой расположено данное изображение. В меню справа в таком случае также доступна функция Поиск по картинке.

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

Существуют также расширения для браузеров Google Chrome или  Firefox, с помощью которых можно выполнять поиск по картинкам в Интернете, просто нажимая на нужное изображение правой кнопкой мыши. В  Chrome это выглядит примерно так:

В Opera всё немного  печальнее, но тоже возможно реализовать данную функцию. Открываете любую страницу поисковика  Google и кликаете правой кнопкой мыши. В контекстном меню выбираете “Настройки для сайта”

Затем вкладку “Сеть” и в поле “Идентификация браузера” выбираем “Представляться как Firefox”.

 

После обновления страницы функция Search by Image станет доступной и в Opera. Есть также неплохое видео, поясняющее как настроить данную функцию

 [youtube]http://www.youtube.com/watch?v=KuPetpKb-vc[/youtube]

Можно пойти дальше и установить расширенное меню в котором “включена” данная функция. После установки меню при клике правой кнопкой мыши по изображению, доступна функция “Распознать с Google image”. Узнать как скачать и установить меню можно в статье Смена темы оформления и профиля меню в Opera.  Из трёх меню выбирайте standard_menu (1).ini.

Похожие записи

z-force.info

Яндекс Алиса распознаёт фотографии и изображения

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

В июне 2018-го года Алиса научилась искать информацию по фотографиям с камеры или любым другим изображениям, которые вы ей предоставите. На основе загруженного изображения помощник может сделать некоторые полезные действия. Отметим, что до появления Алисы приложение «Яндекс» уже умело распознавать изображения, но это работало не так удобно и красиво, как выглядит в Алисе. Поиск и анализ необходимой информации стал ещё быстрее и точнее. Мы используем эту новую функцию помощника сами, и рекомендуем воспользоваться ею и вам.

Очевидно, что в умной колонке Яндекс Станция возможности работы с изображениями отсутствуют. Для того, чтобы использовать эти функции вам нужно приложение Яндекс и Яндекс.Браузер.

Где скачать Алису с поиском по картинкам

Компания Яндекс встроила голосовой ассистент Алиса в приложение под названием «Яндекс» на платформах Android и iOS. Скачать Яндекс с Алисой можно по этим ссылкам:

Платформа: Android

Цена: Бесплатно

Платформа: iOS

Цена: Бесплатно

Как включить поиск по картинкам в Алисе

  1. Чтобы открыть Алису нажимаем на красный значок приложения «Яндекс».
  2. Первый способ открыть функцию распознавания изображений: нажимаем на серый значок фотоаппарата с лупой в поисковой строке и переходим к шагу 4. Второй способ: нажимаем на фиолетовый значок Алисы или говорим «Привет, Алиса!» если у вас включена голосовая активация.
  3. Откроется диалог (чат) с Алисой. Нужно дать команду Алисе «Распознай изображение» или «Сделай фото». Также вы можете нажать на серый значок фотоаппарата с лупой.
  4. Приложение попросит доступ к камере вашего мобильного устройства. Нажимаем «Разрешить».
  5. Откроется режим съёмки. Здесь вы можете загрузить изображение из вашей галлереи или сделать новый снимок прямо сейчас. Нажмите на фиолетовый круг, чтобы сделать снимок.
  6. Алиса распознает объект на изображении.
  7. Давайте попробуем загрузить фотографию из памяти, т.е. галереи вашего iPhone или Android. Нажимаем на иконку с фотографией.
  8. Алиса попросит доступ к вашим фотографиям. Нажимаем «Разрешить».
  9. Выбираем фотографию.
  10. Через некоторое время фотография загрузится на сервера Яндекса и Алиса вам скажет, на что похоже загруженное изображение. В нашем случае мы загрузили фотографию умной колонки Amazon Echo Dot, и Алиса её успешно распознала.

Возможности Алисы по распознаванию изображений и список команд

Помимо общей команды «сделай фото», Алисе можно дать более точную команду по распознаванию объекта. Алиса умеет делать следующие операции с изображениями по соответствующим командам:

Узнать знаменитость по фото

  • Кто на фотографии?
  • Что за знаменитость на фотографии?

 

Алиса распознаёт фото знаменитых людей. Мы загрузили изображение актёра Константина Хабенского и Алиса успешно распознала его.

Распознать надпись или текст и перевести его

  • Распознай текст
  • Распознай и переведи надпись

 

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

— Загрузить фото с текстом.
— Прокрутить вниз.
— Нажать «Найти и перевести текст».

— Откроется распознанный текст. Нажимаем «Перевести».
— Откроется Яндекс.Переводчик с переведённым текстом.

Узнать марку и модель автомобиля

  • Определи марку автомобиля
  • Распознай модель автомобиля

 

Алиса умеет определять марки автомобилей. Например, она без труда распознаёт новый автомобиль Nissan X-Trail, в который встроена мультимедийная система Яндекс.Авто с Алисой и Яндекс.Навигатором.

Узнать породу животного

  • Распознай животное
  • Определи породу собаки

 

Алиса умеет распознавать животных. Например, Алиса распознала не только, что на фото собака, но и точно определила породу Лабрадор по фото.

Узнать вид растения

  • Определи вид растения
  • Распознай растение

 

Если вы встретили экзотическое растение, Алиса поможет вам узнать его название.

 

Узнать автора и название картины

  • Распознай картину
  • Определи что за картина

 

Если вы увидели картину и хотите узнать её название, автора и описание, просто попросите Алису вам помочь. Картину «Утро в сосновом лесу» художника Ивана Ивановича Шишкина Алиса определяет моментально.

Найти предмет в Яндекс.Маркет

  • Определи товар
  • Найди товар

 

Если вы увидите интересный предмет, который вы не прочь были бы приобрести – вы можете попросить Алису найти похожие на него товары. Найденный товар вы можете открыть на Яндекс Маркете и там прочитать его характеристики, или сразу заказать.

Распознать QR-код

  • Определи Кью Эр код
  • Распознай Кью Эр код

 

Алиса пока не так быстро и качественно распознаёт QR коды, нам потребовалось несколько попыток, чтобы успешно распознать QR код.

 

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

Яндекс постоянно добавляет новые команды для Алисы. Мы сделали приложение со справкой по командам, которое регулярно обновляем. Установив это приложение, у вас всегда будет под рукой самый актуальный список команд:

Платформа: Android

Цена: Бесплатно

Платформа: iOS

Цена: Бесплатно

Задавайте вопросы в комментариях, подписывайтесь на YouTube канал и Яндекс Дзен Канал, чтобы не пропустить статьи и видео об Алисе.

Поделиться в соц. сетях
Похожие статьи

voiceapp.ru

Что вы видите на этой картинке? — Блог Яндекса

25 марта 2015, 13:11

Распознавание изображений — одна из самых сложных задач для компьютера. Мы уже рассказывали о том, как устроено компьютерное зрение и как оно применяется в наших сервисах — например, при поиске похожих изображений в Яндекс.Картинках. Теперь технология компьютерного зрения работает и в Яндекс.Диске — благодаря ей вы можете найти изображения форматов JPEG, GIF и PNG, содержащие текст поискового запроса. Достаточно ввести в поисковую строку нужное слово, и система найдёт на Диске картинки, на которых оно встретится. В результатах поиска вы увидите изображения с этим словом, документы, в тексте которых оно содержится, а также файлы и папки, в названиях и описаниях которых есть это слово.

Когда на Диске тысячи фотографий, разложенных по разным папкам, поиск по текстам позволит быстро найти среди них нужную. Например, скан договора с названием вроде scan723.JPG или фотографию визитки человека, с которым понадобилось связаться. Искать можно не только документы, но и любые фотографии, которые сделаны для того, чтобы сохранить текст, будь то объявление на двери подъезда или любопытный рекламный плакат в метро.

В основе поиска текстов на изображениях лежит технология оптического распознавания символов. Систем распознавания, опирающихся на эту технологию, много, и все они разные. Какие-то решают определённую задачу, например распознают партитуры, какие-то работают только с чистым текстом. Для Яндекс.Диска мы разработали свою универсальную систему, способную распознавать текст на картинках разных по виду, содержанию и, главное, качеству.

Система состоит из двух частей — классификатора картинок и модуля распознавания. Сначала классификатор, глубокая нейронная сеть, отбирает из всех картинок те, на которых изображён текст. Он учится отличать их от прочих на огромной базе изображений. Использование машинного обучения позволяет добиться высокого качества распознавания — ведь алгоритм опирается не на какие-то вручную заданные правила, а на опыт анализа миллионов разных картинок. Когда изображения с текстом отобраны, алгоритм находит на них линии, предположительно содержащие текст, — различать их помогает ещё одна нейронная сеть. На следующем этапе алгоритм оставляет только те линии текста, в которых он уверен.

Затем модуль распознавания разбивает линии текста на отдельные символы. Для каждого символа алгоритм выбирает несколько наиболее вероятных вариантов распознавания среди известных ему. Например, это могут быть буквы «О», «о» и цифра «0», очень похожие друг на друга. После этого в дело вступает языковая модель — алгоритм принимает решение, какой из символов-кандидатов подходит лучше всего. Языковая модель опирается на словари и учитывает не только сходство символов с теми, что знает система, но и контекст, то есть соседние символы. Если из нескольких вероятных символов складывается известное системе слово, то она может принять решение, что на картинке написано именно оно. Даже если некоторые символы-кандидаты в этом слове менее вероятны, чем другие.

Конечно, точность распознавания текста (а значит, и успех поиска) зависит от типа изображения, его чёткости, фона, на котором находится текст, и многих других факторов. Поэтому для разных видов изображений она разная. Например, для отсканированных документов точность распознавания текстов на русском языке составляет около 80%, для фотографий с надписями — 63,2%, а для скриншотов приближается к 100%. Помимо русского языка, система также распознаёт английский, украинский и турецкий. Точность распознавания текстов всего потока изображений более 70%. Это неплохой результат, но мы будем работать над его улучшением.

yandex.ru

Чтобы распознавать картинки, не нужно распознавать картинки / Хабрахабр

Посмотрите на это фото.

Это совершенно обычная фотография, найденная в Гугле по запросу «железная дорога». И сама дорога тоже ничем особенным не отличается.

Что будет, если убрать это фото и попросить вас нарисовать железную дорогу по памяти?

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


Упс. Кажется, что-то пошло не так.


Давайте еще раз вернемся к рельсам на первой картинке и попробуем понять, что не так.

На самом деле, если долго разглядывать ее, становится понятно, что она не совсем точно отображает окружающий мир. Главная проблема, о которую мы немедленно споткнулись — там, например, пересекаются параллельные прямые. Ряд одинаковых (в реальности) фонарных столбов на самом деле изображен так, что каждый следующий столб имеет все меньшие и меньшие размеры. Деревья вокруг дороги, у которых поначалу различимы отдельные ветки и листья, сливаются в однотонный фон, который еще и вдобавок почему-то приобретает отчетливо-фиолетовый оттенок.
Все это — эффекты перспективы, последствия того, что трехмерные объекты снаружи проецируются на двумерную сетчатку внутри глаза. Ничего отдельно магического в этом нет — разве что немного любопытно, почему эти искажения контуров и линий не вызывают у нас никаких проблем при ориентации в пространстве, но вдруг заставляют мозг напрячься при попытке взяться за карандаш.

Еще один замечательный пример — как маленькие дети рисуют небо.


Небо должно быть наверху — вот она, синяя полоска, пришпиленная к верхнему краю. Середина листа при этом остается белой, заполнена пустотой, в которой плавает солнце.

И так происходит всегда и везде. Мы знаем, что куб состоит из квадратных граней, но посмотрите на картинку, и вы не увидите там ни одного прямого угла — более того, эти углы постоянно меняются, стоит сменить угол обзора. Как будто где-то в голове у нас сохранена грубая схема правильного, трехмерного объекта, и именно к ней мы обращаемся в процессе рисования рельс, не сразу успевая сопоставить результат с тем, что видим своими глазами.

На самом деле все еще хуже. Каким образом, например, на самой первой картинке с дорогой мы определяем, какая часть дороги расположена ближе к нам, а какая дальше? По мере удаления предметы становятся меньше, ок — но вы уверены, что кто-то не обманул вас, коварно разместив друг за другом последовательно уменьшающиеся шпалы? Далекие объекты обычно имеют бледно-голубоватый оттенок (эффект, который называется «атмосферная перспектива») — но предмет может быть просто окрашен в такой цвет, и в остальном казаться совершенно нормальным. Мост через железнодорожные пути, который едва видно отсюда, кажется нам находящимся позади, потому что его заслоняют фонари (эффект окклюзии) — но опять-таки, как вы можете быть уверены, что фонари просто не нарисованы на его поверхности? Весь этот набор правил, с помощью которых вы оцениваете трехмерность сцены, во многом зависит от вашего опыта, и возможно, генетического опыта ваших предков, обученных выживать в условиях нашей атмосферы, падающего сверху света и ровной линии горизонта.

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

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

Представьте, что вы — нейронная сеть.

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

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

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

Самое обидное, что не видно, как можно решить этот вопрос механическим способом. Компьютерное зрение сталкивалось с соответствующими проблемами очень давно, с момента своего появления, и периодически находило эффективные частные решения — так, мы можем опознать сдвинутый в сторону предмет, последовательно передвигая свой проверочный паттерн по всему изображению (чем успешно пользуются сверточные сети), можем справляться с отмасштабированными или повернутыми картинками с помощью признаков SIFT, SURF и ORB, но эффекты перспективы и поворот предмета в пространстве сцены — похоже, вещи качественно другого уровня. Здесь нам нужно знать, как предмет выглядит со всех сторон, получить его истинную трехмерную форму, иначе нам не с чем работать. Поэтому чтобы распознавать картинки, не нужно распознавать картинки. Они лживы, обманчивы и заведомо неполноценны. Они — не наши друзья.


Итак, важный вопрос — как бы нам получать трехмерную модель всего, что мы видим? Еще более важный вопрос — как при этом обойтись без необходимости покупать лазерный пространственный сканер (сначала я написал «чертовски дорогой лазерный сканер», а потом наткнулся на этот пост)? Даже не столько по той причине, что нам жалко, а потому, что животные в процессе эволюции зрительной системы явно каким-то образом обошлись без него, одними только глазами, и было бы любопытно выяснить, как они так.

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

Вообще с двумя глазами все не так просто

Для некоторых действий они, похоже, и правда приносят пользу с точки зрения оценки пространственного положения. Возьмите два карандаша, закройте один глаз и попытайтесь сдвигать эти карандаши так, чтобы они соприкоснулись кончиками грифелей где-то вблизи вашего лица. Скорее всего, грифели разойдутся, причем ощутимо (если у вас получилось легко, поднесите их еще ближе к лицу), при этом со вторым открытым глазом такого не происходит. Пример взят из книги Марка Чангизи «Революция в зрении» — там есть целая глава о стереопсисе и бинокулярном зрении с любопытной теорией о том, что два смотрящих вперед глаза нужны нам для того, чтобы видеть сквозь мелкие помехи вроде свисающих листьев. Кстати, забавный факт — на первом месте в списке преимуществ бинокулярного зрения в Википедии стоит «It gives a creature a spare eye in case one is damaged».

Итак, бинокулярное зрение нам не подходит — и вместе с ним мы отвергаем стереокамеры, дальномеры и Kinect. Какой бы ни была способость нашей зрительной системы воссоздавать трехмерные образы увиденного, она явно не требует наличия двух глаз. Что остается в итоге?

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

Вернемся к теме поездов, только на этот раз выглянем из окна:

То, что мы при этом видим, называется «параллакс движения», и вкратце он заключается в том, что когда мы двигаемся вбок, близкие предметы смещаются в поле зрения сильнее, чем далекие. Для движения вперед/назад и поворотов тоже можно сформулировать соответствующие правила, но давайте их пока проигнорируем. Итак, мы собираемся двигаться, оценивать смещения предметов в кадре и на основании этого определять их расстояние от наблюдателя — техника, которая официально называется «structure-from-motion». Давайте попробуем.


Прежде всего — а не сделали ли все, случайно, до нас? Страница «Structure from motion» в Википедии предлагает аж тринадцать инструментов (и это только опенсорсных) для воссоздания 3D-моделей из видео или набора фотографий, большинство из них пользуются подходом под названием bundle adjustment, а самым удобным мне показался Bundler (и демо-результаты у него крутые). К сожалению, тут возникает проблема, с которой мы еще столкнемся — Bundler для корректной работы хочет знать от нас модель камеры и ее внутренние параметры (в крайнем случае, если модель неизвестна, он требует указать фокусное расстояние).

Если для вашей задачи это не проблема — можете смело бросать чтение, потому что это самый простой и одновременно эффективный метод (а знаете, кстати, что примерно таким способом делались модели в игре «Исчезнование Итана Картера»?). Для меня, увы, необходимость быть привязанным к модели камеры — это условие, которого очень хотелось бы избежать. Во-первых, потому что у нас под боком полный ютуб визуального видео-опыта, которым хотелось бы в будущем пользоваться в качестве выборки. Во-вторых (и это, может быть, даже важнее), потому что наш с вами человеческий мозг, похоже, если и знает в цифрах внутренние параметры камеры наших глаз, то прекрасно умеет приспосабливаться к любым оптическим искажениями. Взгляд через объектив широкофокусной камеры, фишай, просмотр кино и ношение окулусрифта совершенно не разрушает ваших зрительных способностей. Значит, наверное, возможен и какой-то другой путь.

Итак, мы печально закрыли страницу с Итаном Картером википедии и опускаемся на уровень ниже — в OpenCV, где нам предлагают следующее:

1. Взять два кадра, снятые с откалиброванной камеры.
2. Вместе с параметрами калибровки (матрицей камеры) положить их оба в функцию stereoRectify, которая выпрямит (ректифицирует) эти два кадра — это преобразование, которое искажает изображение так, чтобы точка и ее смещение оказывались на одной горизонтальной прямой.
3. Эти ректифицированые кадры мы кладем в функцию stereoBM и получаем карту смещений (disparity map) — такую картинку в оттенках серого, где чем пиксель ярче, тем большее смещение он выражает (по ссылке есть пример).
4. Полученную карту смещений кладем в функцию с говорящим названием reprojectImageTo3D (понадобится еще и матрица Q, которую в числе прочих мы получим на шаге 2). Получаем наш трехмерный результат.

Черт, похоже, мы наступаем на те же грабли — уже в пункте 1 от нас требуют откалиброванную камеру (правда, OpenCV милостиво дает возможность сделать это самому). Но погодите, здесь есть план Б. В документации прячется функция с подозрительным названием stereoRectifyUncalibrated…

План Б:

1. Нам нужно оценить примерную часть смещений самим — хотя бы для ограниченного набора точек. StereoBM здесь не подойдет, поэтому нам нужен какой-то другой способ. Логичным вариантом будет использовать feature matching — найти какие-то особые точки в обоих кадрах и выбрать сопоставления. Про то, как это делается, можно почитать здесь.
2. Когда у нас есть два набора соответствующих друг другу точек, мы можем закинуть их в findFundamentalMat, чтобы получить фундаментальную матрицу, которая понадобится нам для stereoRectifyUncalibrated.
3. Запускаем stereoRectifyUncalibrated, получаем две матрицы для ректификации обоих кадров.
4. И… а дальше непонятно. Выпрямленные кадры у нас есть, но нет матрицы Q, которая была нужна для завершающего шага. Погуглив, я наткнулся примерно на такой же недоумения пост, и понял, что либо я что-то упустил в теории, либо в OpenCV этот момент не продумали.

OpenCV: мы — 2:0.

4.1 Меняем план


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

Это все прекрасно, но вообще говоря, нам не нужно. Реальные размеры предметов интересовали бы нас, если бы наша модель использовалась потом для промышленных целей, в каких-нибудь 3d-принтерах. Но мы собираемся (эта цель слегка уже расплылась, правда) запихивать полученные данные в нейросети и им подобные классификаторы. Для этого нам достаточно знать только относительные размеры предметов. Они, как мы все еще помним, обратно пропорциональны смещениям параллакса — чем дальше от нас предмет, тем меньше смещается при нашем движении. Нельзя ли как-то найти эти смещения еще проще, просто каким-то образом сопоставив обе картинки?

Само собой, можно. Привет, оптический поток.

Это замечательный алгоритм, который делает ровно то, что нам нужно. Кладем в него картинку и набор точек. Потом кладем вторую картинку. Получаем на выходе для заданных точек их новое положение на второй картинке (приблизительное, само собой). Никаких калибровок и вообще никаких упоминаний о камере — оптический поток, несмотря на название, можно рассчитывать на базе чего угодно. Хотя обычно он все-таки используется для слежения за объектами, обнаружения столкновений и даже дополненной реальности.

Для наших целей мы (пока) хотим воспользоваться «плотным» потоком Гуннара Фарнебака, потому что он умеет рассчитывать поток не для каих-то отдельных точек, а для всей картинки сразу. Метод доступен с помощью calcOpticalFlowFarneback, и первые же результаты начинают очень-очень радовать — смотрите, насколько оно выглядит круче, чем предыдущий результат stereoRectifyUncalibrated + stereoBM.


Большое спасибо замечательной игре Portal 2 за возможность строить собственные комнаты и играть в кубики. I’m doin’ Science!

Код для для этой маленькой демонстрации
# encoding: utf-8

import cv2
import numpy as np
from matplotlib import pyplot as plt

img1 = cv2.imread('0.jpg', 0)
img2 = cv2.imread('1.jpg', 0)


def stereo_depth_map(img1, img2):
    # 1: feature matching
    orb = cv2.ORB()
    kp1, des1 = orb.detectAndCompute(img1, None)
    kp2, des2 = orb.detectAndCompute(img2, None)

    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    matches = bf.match(des1, des2)
    matches = sorted(matches, key=lambda x: x.distance)

    src_points = np.vstack([np.array(kp1[m.queryIdx].pt) for m in matches])
    dst_points = np.vstack([np.array(kp2[m.trainIdx].pt) for m in matches])

    # 2: findFundamentalMat
    F, mask = cv2.findFundamentalMat(src_points, dst_points)

    # 3: stereoRectifyUncalibrated
    _, h2, h3 = cv2.stereoRectifyUncalibrated(src_points.reshape(src_points.shape[
                                              0], 1, 2), dst_points.reshape(dst_points.shape[0], 1, 2), F, img1.shape)

    rect1 = cv2.warpPerspective(img1, h2, (852, 480))
    rect2 = cv2.warpPerspective(img2, h3, (852, 480))

    # 3.5: stereoBM
    stereo = cv2.StereoBM(cv2.STEREO_BM_BASIC_PRESET, ndisparities=16, SADWindowSize=15)
    return stereo.compute(rect1, rect2)


def optical_flow_depth_map(img1, img2):
    flow = cv2.calcOpticalFlowFarneback(img1, img2, 0.5, 3, 20, 10, 5, 1.2, 0)
    mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
    return mag


def plot(title, img, i):
    plt.subplot(2, 2, i)
    plt.title(title)
    plt.imshow(img, 'gray')
    plt.gca().get_xaxis().set_visible(False)
    plt.gca().get_yaxis().set_visible(False)

plot(u'Первый кадр', img1, 1)
plot(u'Второй кадр (шаг вправо)', img2, 2)
plot(u'stereoRectifyUncalibrated', stereo_depth_map(img1, img2), 3)
plot(u'Первый кадр', optical_flow_depth_map(img1, img2), 4)

plt.show()

Итак, отлично. Смещения у нас есть, и на вид неплохие. Как теперь нам получить из них координаты трехмерных точек?

4.2 Часть, в которой мы получаем координаты трехмерных точек


Эта картинка уже мелькала на одной из ссылок выше.

Расстояние до объекта здесь рассчитывается методом школьной геометрии (подобные треугольники), и выглядит так: . А координаты, соответственно, вот так: . Здесь w и h — ширина и высота картинки, они нам известны, f — фокусное расстояние камеры (расстояние от центра камеры до поверхности ее экрана), и B — камеры же шаг. Кстати, обратите внимание, что мы тут слегка нарушаем общепринятые названия осей, когда Z направлена вверх — у нас Z смотрит «вглубь» экрана, а X и Y — соответственно, направлены по ширине и высоте картинки.

Ну, насчет f все просто — мы уже оговаривали, что реальные параметры камеры нас не интересуют, лишь бы пропорции всех предметов изменялись по одному закону. Если подставить Z в формулу для X выше, то можно увидеть, что X от фокусного расстояния вообще не зависит (f сокращается), поэтому разные его значения буду менять только глубину — «вытягивать» или «сплющивать» нашу сцену. Визуально — не очень приятно, но опять же, для алгоритма классификации — совершенно все равно. Так что зададим фокусное расстояние интеллектуальным образом — просто придумаем. Я, правда, оставляю за собой право слегка изменить мнение дальше по тексту.

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

Настало время написать немного кода
import cv2
import numpy as np

f = 300   # раз мы занимаемся визуализацией, фокус я все-таки подобрал так, чтобы сцена выглядела условно реальной
B = 1
w = 852
h = 480

img1 = cv2.imread('0.jpg', 0)
img2 = cv2.imread('1.jpg', 0)

flow = cv2.calcOpticalFlowFarneback(img1, img2, 0.5, 3, 20, 10, 5, 1.2, 0)
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])

edges = cv2.Canny(img1, 100, 200)

result = []
for y in xrange(img1.shape[0]):
    for x in xrange(img1.shape[1]):
        if edges[y, x] == 0:
            continue
        delta = mag[y, x]
        if delta == 0:
            continue
        Z = (B * f) / delta
        X = (Z * (x - w / 2.)) / f
        Y = (Z * (y - h / 2.)) / f
        point = np.array([X, Y, Z])
        result.append(point)

result = np.vstack(result)


def dump2ply(points):
    # сохраняем в формат .ply, чтобы потом открыть Блендером
    with open('points.ply', 'w') as f:
        f.write('ply\n')
        f.write('format ascii 1.0\n')
        f.write('element vertex {}\n'.format(len(points)))
        f.write('property float x\n')
        f.write('property float y\n')
        f.write('property float z\n')
        f.write('end_header\n')
        for point in points:
            f.write('{:.2f} {:.2f} {:.2f}\n'.format(point[0], point[2], point[1]))

dump2ply(result)

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


Для наглядности я взял не все точки подряд, а только границы, выделенные Canny-детектором

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

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


В общем, основная проблема оказалась в том, что какая-то часть точек довольно сильно искажалась. И — тревожный знак, где уже пора было заподозрить неладное — искажалась не случайным образом, а примерно в одних и тех же местах, так что исправить проблему путем последовательного наложения новых точек (из других кадров) не получалось.Выглядело это примерно так:
Лестница сминается, местами превращаясь в аморфный кусок непонятно-чего.

Я очень долго пытался это починить, и за это время перепробовал следующее:

— сглаживать каринку с оптическим потоком: размытие по Гауссу, медианный фильтр и модный билатеральный фильтр, который оставляет четкими края. Бесполезно: предметы наоборот, еще сильнее расплывались.
— пытался находить на картинке прямые линии с помощью Hough transform и переносить их в неизменном прямом состоянии. Частично работало, но только на границах — поверхности по-прежнему оставались такими же искаженными; плюс никуда не получалось деть мысль в духе «а что если прямых линий на картинке вообще нет».
— я даже попытался сделать свою собственную версию оптического потока, пользуясь OpenCVшным templateMatching. Работало примерно так: для любой точки строим вокруг нее небольшой (примерно 10×10) квадрат, и начинаем двигать его вокруг и искать максимальное совпадение (если известно направление движения, то «вокруг» можно ограничить). Получилось местами неплохо (хотя работало оно явно медленнее оригинальной версии):

Слева уже знакомый поток Фарнебака, справа вышеописаный велосипед

С точки зрения шума, увы, оказалось ничуть не лучше.

В общем, все было плохо, но очень логично. Потому что так оно и должно было быть.


Иллюстрация к проблеме. Движение здесь — по-прежнему шаг вправо

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

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

Проблема появляется, когда мы пытаемся отслеживать кусок линии, расположенной параллельно движению. У красной точки нет одного четко выраженного кандидата на роль смещенного близнеца. Их много, все они находятся рядом, и выбрать какого-то одного тем методом, что мы пользуемся, просто невозможно. Это функциональное ограничение оптического потока. Как нас любезно предупреждает википедия в соответствующей статье, «We cannot solve this one equation with two unknown variables», и тут уже ничего не сделаешь.

Совсем-совсем ничего?

Вообще, если честно, то это, наверное, не совсем правда. Вы ведь можете найти на правой картинке соответствие красной точке? Это тоже не очень сложно, но для этого мы мысленно пользуемся каким-то другим методом — находим рядом ближайшую «зеленую точку» (нижний угол), оцениваем расстояние до нее и откладываем соответствующее расстояние на второй грани куба. Алгоритмам оптического потока есть куда расти — этот способ можно было бы и взять на вооружение (если этого еще не успели сделать).


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

Собственно, все оказалось вот так просто. Мы будем рассчитывать тот же самый оптический поток, но только для «зеленых», устойчивых точек. И кстати, в OpenCV о нас уже позаботились. Нужная нам штука называется поток Лукаса-Канаде.

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

С появлением поворотов координаты X и Z у нас смешиваются. Оставим старые формулы для расчета координат относительно камеры, и будем переводить их в абсолютные координаты следующим образом (здесь — координаты положения камеры, альфа — угол поворота):



(игрек — читер; это потому, что мы считаем, что камера не двигается вверх-вниз)

Где-то здесь же у нас появляются проблемы с фокусным расстоянием — помните, мы решили задать его произвольным? Так вот, теперь, когда у нас появилась возможность оценивать одну и ту же точку с разных углов, он начал иметь значение — именно за счет того, что координаты X и Z начали мешаться друг с другом. На самом деле, если мы запустим код, аналогичный предыдущему, с произвольным фокусом, мы увидим примерно вот что:


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

К счастью, у нас все еще есть оптический поток. При повороте мы можем увидеть, какие точки переходят в какие, и рассчитать для них координаты с двух углов зрения. Отсюда несложно получить фокусное расстояние (просто возьмите две вышеприведенных формулы для разных значений альфа, приравняйте координаты и выразите f). Так гораздо лучше:


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

И, наконец, нам нужно как-то справляться с шумом, благодаря которому наши оценки положения точек не всегда совпадают (видите на гифке сверху аккуратные неровные колечки? вместо каждого из них, в идеале, должна быть одна точка). Тут уже простор для творчества, но наиболее адекватный способ мне показался таким:
— когда у нас есть подряд несколько сдвигов в сторону, объединяем информацию с них вместе — так для одной точки у нас будет сразу несколько оценок глубины;
— когда камера поворачивается, мы пытаемся совместить два набора точек (до поворота и после) и подогнать один к другому. Эта подгонка по-правильному называется «регистрацией точек» (о чем вы бы никогда не догадались, услышав термин в отрыве от контекста), и для нее я воспользовался алгоритмом Iterative closest point, нагуглив версию для питона + OpenCV;
— потом точки, которые лежат в пределах порогового радиуса (определяем методом ближайшего соседа), сливаются вместе. Для каждой точки мы еще отслеживаем что-то типа «интенсивности» — счетчик того, как часто она объединялась с другими точками. Чем больше интенсивность — тем больше шанс на то, что это честная и правильная точка.

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


Голова профессора Доуэля


Какая-то рандомная машина

Бинго! Дальше нужно их все запихать в распознающий алгоритм и посмотреть, что получится. Но это, пожалуй, оставим на следующую серию.


Слегка оглянемся назад и вспомним, зачем мы это все делали. Ход рассуждений был такой:
— нам нужно уметь распознавать вещи, изображенные на картинках
— но эти картинки каждый раз, когда мы меняем положение или смотрим на одну и ту же вещь с разных углов, меняются. Иногда до неузнаваемости
— это не баг, а фича: следствие того, что наши ограниченые сенсоры глаз видят только часть предмета, а не весь предмет целиком
— следовательно, нужно как-то объединить эти частичные данные от сенсоров и собрать из них представление о предмете в его полноценной форме.

Вообще говоря, это ведь наверняка проблема не только зрения. Это скорее правило, а не исключение — наши сенсоры не всемогущи, они постоянно воспринимают информацию об объекте частями — но любопытно, насколько все подобные случаи можно объединить в какой-то общий фреймворк? Скажем (возвращаясь к зрению), ваши глаза сейчас постоянно совершают мелкие и очень быстрые движения — саккады — перескакивая между предметами в поле зрения (а в промежутках между этими движениями ваше зрение вообще не работает — именно поэтому нельзя увидеть собственные саккады, даже уставившись в зеркало в упор). Мозг постоянно занимается упорной работой по «сшиванию» увиденных кусочков. Это — та же самая задача, которую мы только что пытались решить, или все-таки другая? Восприятие речи, когда мы можем соотнести десяток разных вариантов произношения слова с одним его «идеальным» написанием — это тоже похожая задача? А как насчет сведения синонимов к одному «образу» предмета?

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

Очевидные соображения говорят, что когда мы пытаемся воссоздать какую-то штуку, увиденную в природе, нет смысла слепо копировать все ее составные части. Чтобы летать по воздуху, не нужны машущие крылья и перья, достаточно жесткого крыла и подъемной силы; чтобы быстро бегать, не нужны механические ноги — колесо справится гораздо лучше. Вместо того, чтобы копировать увиденное, мы хотим найти принцип и повторить его своими силами (может быть, сделав это проще/эффективней). В чем состоит принцип интеллекта, аналог законов аэродинамики для полета, мы пока не знаем. Deep learning и Ян Лекун, пророк его (и вслед за ним много других людей) считают, что нужно смотреть в сторону способности строить «глубокие» иерархии фич из получаемых данных. Может быть, мы сможем добавить к этому еще одно уточнение — способность объединять вместе релевантные куски данных, воспринимая их как части одного объекта и размещая в новом измерении?

habr.com

Применение нейросетей в распознавании изображений / Хабрахабр

Про нейронные сети, как один из инструментов решения трудноформализуемых задач уже было сказано достаточно много. И здесь, на хабре, было показано, как эти сети применять для распознавания изображений, применительно к задаче взлома капчи. Однако, типов нейросетей существует довольно много. И так ли хороша классическая полносвязная нейронная сеть (ПНС) для задачи распознавания (классификации) изображений?
1. Задача

Итак, мы собрались решать задачу распознавания изображений. Это может быть распознавание лиц, объектов, символов и т.д. Я предлагаю для начала рассмотреть задачу распознавания рукописных цифр. Задача эта хороша по ряду причин:
  • Для распознавания рукописного символа довольно трудно составить формализованный (не интеллектуальный) алгоритм и это становится понятно, стоит только взглянуть на одну и туже цифру написанную разными людьми
  • Задача довольно актуальна и имеет отношение к OCR (optical character recognition)
  • Существует свободно распространяемая база рукописных символов, доступная для скачивания и экспериментов
  • Существует довольно много статей на эту тему и можно очень легко и удобно сравнить различные подходы

В качестве входных данных предлагается использовать базу данных MNIST. Эта база содержит 60 000 обучающих пар (изображение — метка) и 10 000 тестовых (изображения без меток). Изображения нормализованы по размеру и отцентрованы. Размер каждой цифры не более 20х20, но вписаны они в квадрат размером 28х28. Пример первых 12 цифр из обучающего набора базы MNIST приведен на рисунке:

Таким образом задача формулируется следующим образом: создать и обучить нейросеть распознаванию рукописных символов, принимая их изображения на входе и активируя один из 10 выходов. Под активацией будем понимать значение 1 на выходе. Значения остальных выходов при этом должны (в идеале) быть равны -1. Почему при этом не используется шкала [0,1] я объясню позже.
2. «Обычные» нейросети.

Большинство людей под «обычными» или «классическими» нейросетями понимает полносвязные нейронные сети прямого распространения с обратным распространением ошибки:

Как следует из названия в такой сети каждый нейрон связан с каждым, сигнал идет только в направлении от входного слоя к выходному, нет никаких рекурсий. Будем называть такую сеть сокращенно ПНС.
Сперва необходимо решить как подавать данные на вход. Самое простое и почти безальтернативное решение для ПНС — это выразить двумерную матрицу изображения в виде одномерного вектора. Т.е. для изображения рукописной цифры размером 28х28 у нас будет 784 входа, что уже не мало. Дальше происходит то, за что нейросетевиков и их методы многие консервативные ученые не любят — выбор архитектуры. А не любят, поскольку выбор архитектуры это чистое шаманство. До сих пор не существует методов, позволяющих однозначно определить структуру и состав нейросети исходя из описания задачи. В защиту скажу, что для трудноформализуемых задач вряд ли когда-либо такой метод будет создан. Кроме того существует множество различных методик редукции сети (например OBD [1]), а также разные эвристики и эмпирические правила. Одно из таких правил гласит, что количество нейронов в скрытом слое должно быть хотя бы на порядок больше количества входов. Если принять во внимание что само по себе преобразование из изображения в индикатор класса довольно сложное и существенно нелинейное, одним слоем тут не обойтись. Исходя из всего вышесказанного грубо прикидываем, что количество нейронов в скрытых слоях у нас будет порядка 15000 (10 000 во 2-м слое и 5000 в третьем). При этом для конфигурации с двумя скрытыми слоями количество настраиваемых и обучаемых связей будет 10 млн. между входами и первым скрытым слоем + 50 млн. между первым и вторым + 50 тыс. между вторым и выходным, если считать что у нас 10 выходов, каждый из которых обозначает цифру от 0 до 9. Итого грубо 60 000 000 связей. Я не зря упомянул, что они настраиваемые — это значит, что при обучении для каждой из них нужно будет вычислять градиент ошибки.
Ну это ладно, что уж тут поделаешь, красота искусственный интеллект требует жертв. Но вот если задуматься, на ум приходит, что когда мы преобразуем изображение в линейную цепочку байт, мы что-то безвозвратно теряем. Причем с каждым слоем эта потеря только усугубляется. Так и есть — мы теряем топологию изображения, т.е. взаимосвязь между отдельными его частями. Кроме того задача распозравания подразумевает умение нейросети быть устойчивой к небольшим сдвигам, поворотам и изменению масштаба изображения, т.е. она должна извлекать из данных некие инварианты, не зависящие от почерка того или иного человека. Так какой же должна быть нейросеть, чтобы быть не очень вычислительно сложной и, в тоже время, более инвариантной к различным искажениям изображений?
3. Сверточные нейронные сети

Решение этой проблемы было найдено американским ученым французского происхождения Яном ЛеКуном, вдохновленным работами нобелевских лауреатов в области медицины Torsten Nils Wiesel и David H. Hubel. Эти ученые исследовали зрительную кору головного мозга кошки и обнаружили, что существуют так называемые простые клетки, которые особо сильно реагируют на прямые линии под разными углами и сложные клетки, которые реагирую на движение линий в одном направлении. Ян ЛеКун предложил использовать так называемые сверточные нейронные сети [2].
Идея сверточных нейронных сетей заключается в чередовании сверточных слоев (C-layers), субдискретизирующих слоев (S-layers) и наличии полносвязных (F-layers) слоев на выходе.

Такая архитектура заключает в себе 3 основных парадигмы:
  1. Локальное восприятие.
  2. Разделяемые веса.
  3. Субдискретизация.

Локальное восприятие подразумевает, что на вход одного нейрона подается не все изображение (или выходы предыдущего слоя), а лишь некоторая его область. Такой подход позволил сохранять топологию изображения от слоя к слою.
Концепция разделяемых весов предполагает, что для большого количества связей используется очень небольшой набор весов. Т.е. если у нас имеется на входе изображение размерами 32х32 пикселя, то каждый из нейронов следующего слоя примет на вход только небольшой участок этого изображения размером, к примеру, 5х5, причем каждый из фрагментов будет обработан одним и тем же набором. Важно понимать, что самих наборов весов может быть много, но каждый из них будет применен ко всему изображению. Такие наборы часто называют ядрами (kernels). Нетрудно посчитать, что даже для 10 ядер размером 5х5 для входного изображения размерами 32х32 количество связей окажется равным примерно 256000 (сравниваем с 10 млн.), а количество настраиваемых параметров всего 250!
А как же, спросите вы, это скажется на качестве распознавания? Как ни странно, в лучшую сторону. Дело в том, что такое искусственно введенное ограничение на веса улучшает обобщающие свойства сети (generalization), что в итоге позитивно сказывается на способности сети находить инварианты в изображении и реагировать главным образом на них, не обращая внимания на прочий шум. Можно посмотреть на этот подход немного с другой стороны. Те, кто занимался классикой распознавания изображений и знает как это работает на практике (например в военной технике) знают, что большинство таких систем строятся на основе двумерных фильтров. Фильтр представляет собой матрицу коэффициентов, обычно заданную вручную. Эта матрица применяется к изображению с помощью математической операции, называемой сверткой. Суть этой операции в том, что каждый фрагмент изображения умножается на матрицу (ядро) свертки поэлементно и результат суммируется и записывается в аналогичную позицию выходного изображения. Основное свойство таких фильтров заключается в том, что значение их выхода тем больше чем больше фрагмент изображения похож на сам фильтр. Таким образом изображение свернутое с неким ядром даст нам другое изображение, каждый пиксел которого будет означать степень похожести фрагмента изображения на фильтр. Иными словами это будет карта признаков.
Процесс распространения сигнала в C-слое я попытался изобразить на рисунке:

Каждый фрагмент изображения поэлементно умножается на небольшую матрицу весов (ядро), результат суммируется. Эта сумма является пикселом выходного изображения, которое называется картой признаков. Здесь я опустил тот факт, что взвешенная сумма входов еще пропускается через функцию активации (как в любой другой нейросети). На самом деле это может происходить и в S-слое, принципиальной разницы нет. Следует сказать, что в идеале не разные фрагменты проходят последовательно через ядро, а параллельно все изображение проходит через идентичные ядра. Кроме того, количество ядер (наборов весов) определяется разработчиком и зависит от того какое количество признаков необходимо выделить. Еще одна особенность сверточного слоя в том, что он немного уменьшает изображение за счет краевых эффектов.
Суть субдискретизации и S-слоев заключается в уменьшении пространственной размерности изображения. Т.е. входное изображение грубо (усреднением) уменьшается в заданное количество раз. Чаще всего в 2 раза, хотя может быть и не равномерное изменение, например, 2 по вертикали и 3 по горизонтали. Субдискретизация нужна для обеспечения инвариантности к масштабу.
Чередование слоев позволяет составлять карты признаков из карт признаков, что на практике означает способность распознавания сложных иерархий признаков.
Обычно после прохождения нескольких слоев карта признаков вырождается в вектор или даже скаляр, но таких карт признаков становится сотни. В таком виде они подаются на один-два слоя полносвязной сети. Выходной слой такой сети может иметь различные функции активации. В простейшем случае это может быть тангенциальная функция, также успешно используются радиальные базисные функции.
4. Обучение

Для того чтобы можно было начать обучение нашей сети нужно определиться с тем, как измерять качество распознавания. В нашем случае для этого будем использовать самую распространенную в теории нейронных сетей функцию среднеквадратической ошибки (СКО, MSE) [3]:

В этой формуле Ep — это ошибка распознавания для p-ой обучающей пары, Dp — желаемый выход сети, O(Ip,W) — выход сети, зависящий от p-го входа и весовых коэффициентов W, куда входят ядра свертки, смещения, весовые коэффициенты S- и F- слоев. Задача обучения так настроить веса W, чтобы они для любой обучающей пары (Ip,Dp) давали минимальную ошибку Ep. Чтобы посчитать ошибку для всей обучающей выборки просто берется среднее арифметическое по ошибкам для всех обучающих пар. Такую усредненную ошибку обозначим как E.
Для минимизации функции ошибки Ep самыми эффективными являются градиентные методы. Рассмотрим суть градиентных методов на примере простейшего одномерного случая (т.е. когда у нас всего один вес). Если мы разложим в ряд Тейлора функцию ошибки Ep, то получим следующее выражение:

Здесь E — все та же функция ошибки, Wc — некоторое начальное значение веса. Из школьной математики мы помним, что для нахождения экстремума функции необходимо взять ее производную и приравнять нулю. Так и поступим, возьмем производную функции ошибки по весам, отбросив члены выше 2го порядка:

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

Т.е. оптимальный вес вычисляется как текущий минус производная функции ошибки по весу, деленная на вторую производную функции ошибки. Для многомерного случая (т.е. для матрицы весов) все точно также, только первая производная превращается в градиент (вектор частных производных), а вторая производная превращается в Гессиан (матрицу вторых частных производных). И здесь возможно два варианта. Если мы опустим вторую производную, то получим алгоритм наискорейшего градиентного спуска. Если все же захотим учитывать вторую производную, то обалдеем от того сколько вычислительных ресурсов нам потребуется, чтобы посчитать полный Гессиан, а потом еще и обратить его. Поэтому обычно Гессиан заменяют чем-то более простым. Например, один из самых известных и успешных методов — метод Левенберга-Марквардта (ЛМ) заменяет Гессиан, его аппроксимацией с помощью квадрадного Якобиана. Подробности здесь рассказывать не буду.
Но что нам важно знать об этих двух методах, так это то, что алгоритм ЛМ требует обработки всей обучающей выборки, тогда как алгоритм градиентного спуска может работать с каждой отдельно взятой обучающей выборкой. В последнем случае алгоритм называют стохастическим градиентом. Учитывая, что наша база содержит 60 000 обучающих образцов нам больше подходит стохастический градиент. Еще одним преимуществом стохастического градиента является его меньшая подверженность попаданию в локальный минимум по сравнению с ЛМ.
Существует также стохастическая модификация алгоритма ЛМ, о которой я, возможно, упомяну позже.
Представленные формулы позволяют легко вычислить производную ошибки по весам, находящимся в выходном слое. Вычислить ошибку в скрытых слоях позволяет широко известный в ИИ метод обратного распространения ошибки.
5. Реализация

Лично я использую для реализации различных алгоритмов, от которых не требуется функционирование в реальном времени Matlab. Это очень удобный пакет, M-язык которого позволяет сосредоточиться на самом алгоритме не заботясь о выделении памяти, операциях в/в и т.д. Кроме того, множество различных тулбоксов позволяет создавать поистине междисциплинарные приложения в кротчайшие сроки. Можно, например, с помощью Image Acquisition Toolbox подключить вебкамеру, с помощью Image Processing Toolbox обрабатывать изображение с нее, с помощью Neural Network Toolbox формировать траекторию движения робота, а с помощью Virtual Reality Toolbox и Control Systems Toolbox моделировать движение робота. Кстати о Neural Network Toolbox — это довольно гибкий набор инструментов, позволяющий создавать множество нейронных сетей различных типов и архитектур, но, к сожалению, не сверточные НС. Все дело в разделяемых весах. В NN toolbox возможность задавать разделяемые веса отсутствует.
Чтобы устранить этот недостаток мною был написан класс, позволяющий реализовать СНС произвольной архитектуры и применять их к различным задачам. Скачать класс можно здесь. Сам класс был написан так, чтобы тому, кто им пользуется была максимальная видна структура сети. Все очень обильно прокомментировано, на названии переменных не экономил. Скорость симуляции сети неплоха и составляет доли секунды. Скорость обучения пока не велика (>10 ч), но следите за обновлениями, в ближайшее время планируется ускорение на порядки.
Кого интересует реализация СНС на С++, могут найти ее здесь и здесь.
6. Результаты

В программе на matlabcentral прилагается файл уже натренированной нейросети, а также GUI для демонстрации результатов работы. Ниже приведены примеры распознавания:


По ссылке имеется таблица сравнения методов распознавания на базе MNIST. Первое место за сверточными нейросетями с результатом 0.39% ошибок распознавания [4]. Большинство из этих ошибочно распознанных изображений не каждый человек правильно распознает. Кроме того в работе [4] были использованы эластические искажения входных изображений, а также предварительное обучение без учителя. Но об этих методах как нибудь в другой статье.
Ссылки.

  1. Yann LeCun, J. S. Denker, S. Solla, R. E. Howard and L. D. Jackel: Optimal Brain Damage, in Touretzky, David (Eds), Advances in Neural Information Processing Systems 2 (NIPS*89), Morgan Kaufman, Denver, CO, 1990
  2. Y. LeCun and Y. Bengio: Convolutional Networks for Images, Speech, and Time-Series, in Arbib, M. A. (Eds), The Handbook of Brain Theory and Neural Networks, MIT Press, 1995
  3. Y. LeCun, L. Bottou, G. Orr and K. Muller: Efficient BackProp, in Orr, G. and Muller K. (Eds), Neural Networks: Tricks of the trade, Springer, 1998
  4. Ranzato Marc’Aurelio, Christopher Poultney, Sumit Chopra and Yann LeCun: Efficient Learning of Sparse Representations with an Energy-Based Model, in J. Platt et al. (Eds), Advances in Neural Information Processing Systems (NIPS 2006), MIT Press, 2006

P.S. Всем спасибо за комментарии и за отзывы. Это моя первая статья на хабре, так что буду рад видеть предложения, замечания, дополнения.

habr.com

Распознавание лиц по фото онлайн

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

Работа сервисов по распознаванию лиц

Распознавание происходит при помощи встроенной нейросети, которая быстро ищет похожие фотографии по определённым признакам, изначально самым базовым, например, по весу изображения, его разрешению и т. д. Исходя из данной особенности, у вас в результатах поиска могут появиться ссылки на профили/сайты совершенно не того человека, который изображён на фото, но, к счастью, такое случается крайне редко. Обычно находятся люди со схожей внешностью или похожей обстановкой на фото (например, если плохо видно лица).

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

Дополнительно нужно учесть, что если вы хотите по фотографии человека найти его профиль во Вконтакте, то стоит помнить, что в настройках приватности этой социальной сети пользователь может поставить галочки напротив определённых пунктов, из-за чего его страницу не смогут сканировать поисковые роботы и просматривать пользователи, не зарегистрированные в VK. Если у нужного вам человека выставлены таковые настройки приватности, то найти его страницу по фото будет очень сложно.

Способ 1: Яндекс Картинки

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

Перейти на Яндекс Картинки

Инструкция по поиску через данный сервис выглядит так:

  1. На главной странице нажмите на иконку поиска по фотографии. Она выглядит как лупа на фоне фотоаппарата. Находится в верхнем меню, в правой части экрана.
  2. Поиск можно осуществить по URL-адресу картинки (ссылке в интернете) или используя кнопку загрузки изображения с компьютера. Инструкция будет рассмотрена на последнем примере.
  3. При нажатии на «Выберите файл» открывается окошко, где указывается путь к изображению на компьютере.
  4. Подождите некоторое время, пока картинка полностью не загрузится. В верхней части выдачи будет показана эта же картинка, но здесь вы сможете просмотреть её в других размерах. Данный блок нам не интересен.
  5. Ниже вы можете посмотреть теги, которые применимы к загруженному изображению. Используя их, можно найти похожие картинки, но это в поиске информации по конкретной личности вряд ли поможет.
  6. Далее находится блок с похожими фотографиями. Он может оказаться вам полезен, так как в нём по определённому алгоритму подбираются похожие фотографии. Рассмотрим поиск по этому блоку. Если в первых похожих картинках вы не увидели нужное фото, то нажмите «Ещё похожие».
  7. Откроется новая страница, где будут все схожие фото. Предположим, вы нашли ту фотографию, которая вам нужна. Кликните по ней, чтобы её увеличить и узнать подробную информацию.
  8. Здесь обратите внимание на правый блок слайдера. В нём можно найти ещё похожие фотографии, открыть эту в полном размере, а главное — перейти на сайт, где она размещена.
  9. Вместо блока с похожими фото (6-й шаг), можно пролистать страницу чуть ниже, и увидеть на каких сайтах размещено именно то изображение, которое вы загрузили. Данный блок называется «Сайты, где встречается картинка».
  10. Для перехода на интересующий сайт нажмите по ссылке или оглавлению. Не стоит переходить на сайты с сомнительными именами.

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

Способ 2: Google Images

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

Перейти на Google Images

Инструкция выглядит следующим образом:

  1. Перейдя на сайт, в строке поиска нажмите на иконку фотоаппарата.
  2. Выберите вариант загрузки: либо укажите ссылку, либо закачайте изображение с компьютера. Для переключения между вариантами загрузки просто нажмите на одну из надписей в верхней части окошка. В данном случае будет рассмотрен поиск по изображению, которое загружено с компьютера.
  3. Откроется страница с результатами. Здесь, как и в Яндексе, в первом блоке вы можете просмотреть это же изображение, но в других размерах. Под этим блоком находится пара тегов, подходящих по смыслу, и пара сайтов, где есть такая же картинка.
  4. В данном случае рекомендуется рассмотреть подробнее блок «Похожие изображения». Нажмите на заголовок блока, чтобы увидеть больше похожих картинок.
  5. Найдите нужное изображение и кликните по нему. Откроется слайдер по аналогии с Яндекс Картинками. Здесь вы также можете посмотреть это изображение в разных размерах, найти ещё похожие, перейти на сайт, где оно размещено. Для перехода на сайт-источник нужно нажать на кнопку «Перейти» или кликнуть по заголовку в верхней правой части слайдера.
  6. Дополнительно вам может быть интересен блок «Страницы с подходящим изображением». Тут всё аналогично с Яндексом – просто набор сайтов, где встречается точно такое же изображение.

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

Заключение

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

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

Помогла ли вам эта статья?

Да Нет

lumpics.ru

Как распознать текст С КАРТИНКИ без Finereader — Оффтоп на vc.ru

И перевести его

Распознавание и перевод иностранного текста с картинки подручными средствами

Вчера понадобилось быстро перевести французский текст С КАРТИНКИ, а некоторые слова в нём подзабыл.

Текст на иноземном сайте перевести просто: щёлкнул правой кнопкой, “Перевести”, выбрал язык – и voila!

С картинками такой фокус не проходит.

Лезть с каждым словом в Гуглпереводчик, вбивать их туда, конечно же, лениво, поэтому поискал в Гугле “распознавание текста с картинки”.

Как обычно, множество всяких сервисов, основная масса из которых требует – нет, не денег или установки какой-то программы на комп (иногда – трояна). Время подобной наглости, слава Байту, прошло – требуют регистрации, т.е. хотят заполучить мой e-mail, чтобы потом впаривать всякие удлинители и семинары по управлению судьбой.

Предлагаю вашему вниманию простой метод перевода текста с картинки, если вы пользуетесь ГуглПочтой.

1. В Хроме справа вверху кнопаем на “Приложения Google” и выбираем Диск:

Открываем Диск

2. Загружаем картинку в заранее подготовленную папку на Диске:

Загружаем картинку на Диск

3. Кнопаем правой на загруженной картинке и выбираем “Открыть с помощью” / “Google Документы”:

Открываем файл с помощью Документов Гугл

4. Файл открывается в Документах, и текст уже распознан. Его можно выделять, копировать.

Текст распознан

5. В главном меню выбираем “Инструменты” / “Перевести документ”:

Открываем инструмент “Перевод”

6. Выбираем язык перевода:

Выбираем язык

7. Ну, вот и результат. Естественно, есть ошибки, как, впрочем, бывает и в Finereader’е, но они чаще вызваны качеством исходной картинки.

Дальше правим ручками.

Переведённый текст с картинки

Аналогично можно перевести текст с документа Гугл и файла pdf с правами только на просмотр.

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

#кейс

Материал опубликован пользователем. Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать

vc.ru