Применение SURF для создания маркера дополненной реальности
Это продолжение топика о дополненной реальности. Вот здесь первая часть. В обсуждении топика юзером Inco были показаны интересные результаты его работы в направлении распознавании маркера дополненной реальности Видео.На тот момент времени не оказалось, но через пару месяцев мне стало интересно как всё это работает, насколько устойчив подход — и свободные часы нашлись. Представляю вам свою реализацию этой идеи, который вылился в доклад на вот этом событии.
В этом топике внимание будет уделено краткому изложению моего доклада и объяснению того, на что не хватило времени на встрече: исходному коду програмы. Желающие полностью посмотреть и послушать презентацию могут воспользоваться скринкастом:
Что такое дополненная реальность?
Прежде всего я хотел бы остановиться на том, что такое дополненная реальность.
Существует наша реальность — то что мы видим глазами, то как мы это интерпретируем, и то, как это есть на самом деле. Кроме того, есть виртуальная реальность. Это то, что сгенерировано, то что не существует, то что вам хотят показать.
Вот на стыке этих двух реальностей и находится дополненная реальность. Она может смещаться больше в сторону нашей реальности, тогда это будет дополненная реальность, либо она может смещаться больше в сторону виртуальности — тогда это будет виртуальность дополненная нашей реальностью.
Для чего используется дополненная реальность сейчас?
Сейчас она используется:
- Для презентаций и демонстраций. Первое фото, там демонстрируют плотину, это фото с конференции посвященной Aвтокаду
- Интерфейсы. Новые интерфейсы, которые не нужно проецировать. Поставил руку, либо что-нибудь еще(лист бумаги) под камеру, и у тебя готов интерфейс, которым ты можешь управлять объектом.
- Выход в социализацию. Та ситуация, когда ты ведешь своим телефоном по пейзажу, а тебе об этом пейзаже что-то дополнительно сообщают.
Как работает дополненная реальность?
Прежде всего, у нас есть изображение. Почему изображение — потому что человек воспринимает информацию на 70% зрением, т. е. изображение с камеры. Дальше, различные датчики, GPS, гироскопы, акселерометры, компас — они все отдают информацию по устройству, по его ориентации и положению в пространстве.
Например, зная где вы находитесь, и куда смотрит ваш телефон, мы можем сказать, какая у вас перспектива, что вы видите и соответственно, используя эту информацию, вывести дополненную реальность о том, что вы видите, о том, что мы предполагаем, что вы видите. Например из нового:
Далее, обработка изображения, получение информации датчика. На самом деле все не так просто. То изображение, которое мы получаем с камеры, очень часто нуждается в предварительной обработке. Те данные, которые нам отдают датчики — они не точные, если мы возьмем тот-же акселерометр, он безбожно фонит, на высоких частотах, т. е. он постоянно дает нам несколько не те данные которые мы хотели. Аналогично GPS, у него есть порог точности, тот кто работал с GPS с мобильными телефонами знает. Гироскоп — все себе представляют, что это гироскоп как в реактивных самолетах, который дает в трех плоскостях положение. Да, дает в трех плоскостях положение, но без компаса и акселерометра, оно будет недостаточно точным. Опять-таки, дополненная реальность это не только изображение, дополненная реальность учитывает все то, что происходит с устройством.
Идентификация объекта. Это ответ на вопрос, а что-же я вижу. Это самое интересное, вот во всей этой дополненной реальности. Без этого — это все классные игрушки, т. е. покрутить телефон, и у вас машина или мотоцикл влево вправо примет, а если мы идентифицируем:
- где мы находимся — мы можем сделать какой-то вывод о том чтов поле зрения;
- что мы видим — мы можем что-то показать человеку, на том изображении которое он видит.
Ключевая проблема дополненной реальности — что дополнять. Идентифицировать нужно что-то. Для этого существуют алгоритмы распознавания в математике и компьютерных науках. Нашли мы изображение, отлично. А теперь попробуем найти в базе данных изображений. Вот мы скопировали изображение, картину допустим, было-бы интересно узнать что это за картина. Это тоже сложная задача. Как построить индекс, тоже очень интересное направление в компьютерных науках, и естественно, очень много задач.
А как теперь это собственно показать, как пользователю приподнести, чтобы пользователь это понял? Здесь возникает вопрос юзабилити.
Как идентифицировать объект?
Вот, мы получили изображение, и нам нужно идентифицировать объект, маркер, т. е. что-то, относительно чего мы будем дополнять. Это можно сделать с маркерами либо без маркеров. Вот, любой штрих-код, любая надпись, QR-код, это уже маркер. Телефон может его распознать и например дополнить реальность, например, переводом для обычных символов. Например какой-то информацией найденной из интернет для номера автомобиля, для номера дома и т. д.
Геометрическая фигура. Классический маркер дополненной реальности это квадрат. Почему? Потому что довольно просто построить плоскость и найти гомографию. Найти положение в трех координатах.
Графический маркер, который мы создаем, если он имеет четкую форму, такую как квадрат, он выделяется из реальности, соответственно он вносит диссонанс в интерьер. Если маркер близок к реальности, если он входит в эту реальность — он лучше. Фотография — лучше чем нарисованный квадрат, картина -лучше чем QR-код. Теперь смотрите, без маркеров, мы можем получить наши координаты, положение в пространстве, и конечно же графический маркер, который на самом деле маркером может и не быть. Мы можем распознавать часть нашей реальности и потом сказать, да это был наш маркер. Опять таки, можно заранее сгенерировать изображение, если мы хотим чтобы люди что-то узнавали. Мы создаем маркер, например картину, которую вешаем на стену.
Что может быть маркером.
Если мы берем маркеры дополненной реальности, есть несколько систем, которые разрабатываются с начала девяностых годов. Вот ссылка на топик где я подробно описывал маркерные технологии дополненной реальности.
Вот гравюра Дюрера — носорог. Может ли она быть маркером? Да может.
Соответственно, как? Вот для этого собственно и существует метод SURF. Вот отличная статья, которая очень хорошо описывает методику поиска устойчивых признаков.
Если вдумчиво разобраться в методе, посмотреть исходные (раз,два, три) публикации, то появятся такие выводы(подробней об этом в скринкасте):
- Метод имеет чувствительность, которую необходимо настраивать.
- Метод дает ложные срабатывания.
- При построении метода используются эмпирические коэффициенты, которые также нуждаются в подстройке для частного случая.
- Метод имеет предпосылки для распаралелливания и оптимизации.
И самое основное — для использования в законченном приложении дополненной реальности, мало распознать маркер, нужно уметь следить за ним, производить «трекинг» и гасить ложные срабатывания, аноамальные выбросы точек, которые нам может давать SURF, если мы делаем трекинг именно эти методом.
Как найти координаты объекта в кадре и наложить видео?
Вот статья, где описывается математика для трехмерного случая(Когда мы пытемся наложить на наш маркер 3D модель). Для двухмерного случая все намного проще.
Необходимо по нескольким точкам (четыре и больше) найти параметры афинных преобразований, которые подскажут нам как сжать, развернуть, исказить изображение так, чтобы найденные нами ключевые точки совпали.
Вот отсюда и опасность ложных срабатываний. Если мы возьмем «не те» точки — результатом будет неправильно найденная матрица преобразования, и наше изображение будет не там. Как с этим бороться — есть несколько подходов, но все они сводятся к тому, как определить аномальные уровни данных в наблюдениях. Т.е. групировка и кластеризация.
Код
Для реализации этой программы нам понадобится установленая библиотека OpenCV. Данный код писался для Linux, но должен компилироваться и в Visual C. Ссылка на исходники: Opensurf.zip
Кратко, что делает код:
Данный исходный код основывается на проекте OpenSurf, модифицирован файл main.cpp
Собственно, чего хотелось бы коснуться (фрагменты файла main.cpp):
Исходные данные:
// Открываем видеофайл для потока, который будем накладывать
CvCapture* capture1 = cvCaptureFromFile("imgs/ribky.avi");
// Открываем видеофайл для исходного потока(capture), он также может быть и из камеры
CvCapture* capture = cvCaptureFromFile("imgs/child_book.avi");
//CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
// Изображение - маркер
// This is the reference object we wish to find in video frame
IplImage *img = cvLoadImage("imgs/marker6.png");
Получаем ключевые точки:
// Получаем фрэйм
img = cvQueryFrame(capture);
frm_id++;
// Определяем ключевые точки
surfDetDes(img, ipts, false, 4, 4, 2, 0.001f);
// Сравниваем полученные точки с эталоном
getMatches(ipts,ref_ipts,matches);
Построение рамки и рисование зеленых точек на первых сорока фреймах вполне прозрачно, потому переходим прямо к наложению кадров из видео:
//Берем фрэйм из видео для наложения
frame = cvQueryFrame(capture1);
//Изменяем размерн согласно найденномуколичеству точек
pt1.resize(n);
pt2.resize(n);
// Копируем найденные точки в вектора
for(int i = 0; i < n; i++ )
{
pt1[i] = cvPoint2D32f(matches[i].second.x, matches[i].second.y);
pt2[i] = cvPoint2D32f(matches[i].first.x, matches[i].first.y);
}
_pt1 = cvMat(1, n, CV_32FC2, &pt1[0] );
_pt2 = cvMat(1, n, CV_32FC2, &pt2[0] );
// Находи гомографию(матрицу трансформации между двумя наборами точек)
cvFindHomography(&_pt1, &_pt2, &_h, CV_RANSAC, 5);
//Обнуляем изображение
cvZero(frame1);
//Применяем матрицу гомографию, и заливаем все что вне полученного изображения специальным цветом 0,255,0
cvWarpPerspective(frame, frame1, &_h, CV_WARP_FILL_OUTLIERS,cvScalar(0,255,0) );
//Игры с цветом 0,255,0 нужны для того чтобы наложить трансформированное изображение с прозрачностью
//создаем маску для изображения = not (0,253..255,0)
imagegr=cvCreateImage(cvGetSize(frame1), frame1->depth, 1);
cvInRangeS(frame1,
cvScalar(0, 253, 0),
cvScalar(0, 255, 0),
imagegr
);
cvNot(imagegr, imagegr);
//Копируем с маской, чтобы что имеет цвет 0,253... 255,0 стало прозрачным
cvCopy(frame1,img,imagegr);
В свете создания очков Google и растущего интереса к дополненной реальности, целью выступления было описать метод, поделиться с людьми идеями и мыслями, которые многократно умножаются в процессе обсуждения.
Автор: shadoof