Применение SURF для создания маркера дополненной реальности

    Применение SURF для создания маркера дополненной реальности


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


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

    Что такое дополненная реальность?

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

    Для чего используется дополненная реальность сейчас?


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

    Как работает дополненная реальность?


    Прежде всего, у нас есть изображение. Почему изображение — потому что человек воспринимает информацию на 70% зрением, т. е. изображение с камеры. Дальше, различные датчики, GPS, гироскопы, акселерометры, компас — они все отдают информацию по устройству, по его ориентации и положению в пространстве.
    Например, зная где вы находитесь, и куда смотрит ваш телефон, мы можем сказать, какая у вас перспектива, что вы видите и соответственно, используя эту информацию, вывести дополненную реальность о том, что вы видите, о том, что мы предполагаем, что вы видите. Например из нового:
    Далее, обработка изображения, получение информации датчика. На самом деле все не так просто. То изображение, которое мы получаем с камеры, очень часто нуждается в предварительной обработке. Те данные, которые нам отдают датчики — они не точные, если мы возьмем тот-же акселерометр, он безбожно фонит, на высоких частотах, т. е. он постоянно дает нам несколько не те данные которые мы хотели. Аналогично GPS, у него есть порог точности, тот кто работал с GPS с мобильными телефонами знает. Гироскоп — все себе представляют, что это гироскоп как в реактивных самолетах, который дает в трех плоскостях положение. Да, дает в трех плоскостях положение, но без компаса и акселерометра, оно будет недостаточно точным. Опять-таки, дополненная реальность это не только изображение, дополненная реальность учитывает все то, что происходит с устройством.
    Идентификация объекта. Это ответ на вопрос, а что-же я вижу. Это самое интересное, вот во всей этой дополненной реальности. Без этого — это все классные игрушки, т. е. покрутить телефон, и у вас машина или мотоцикл влево вправо примет, а если мы идентифицируем:

    • где мы находимся — мы можем сделать какой-то вывод о том чтов поле зрения;
    • что мы видим — мы можем что-то показать человеку, на том изображении которое он видит.

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

    Как идентифицировать объект?


    Вот, мы получили изображение, и нам нужно идентифицировать объект, маркер, т. е. что-то, относительно чего мы будем дополнять. Это можно сделать с маркерами либо без маркеров. Вот, любой штрих-код, любая надпись, QR-код, это уже маркер. Телефон может его распознать и например дополнить реальность, например, переводом для обычных символов. Например какой-то информацией найденной из интернет для номера автомобиля, для номера дома и т. д.
    Геометрическая фигура. Классический маркер дополненной реальности это квадрат. Почему? Потому что довольно просто построить плоскость и найти гомографию. Найти положение в трех координатах.
    Графический маркер, который мы создаем, если он имеет четкую форму, такую как квадрат, он выделяется из реальности, соответственно он вносит диссонанс в интерьер. Если маркер близок к реальности, если он входит в эту реальность — он лучше. Фотография — лучше чем нарисованный квадрат, картина -лучше чем QR-код. Теперь смотрите, без маркеров, мы можем получить наши координаты, положение в пространстве, и конечно же графический маркер, который на самом деле маркером может и не быть. Мы можем распознавать часть нашей реальности и потом сказать, да это был наш маркер. Опять таки, можно заранее сгенерировать изображение, если мы хотим чтобы люди что-то узнавали. Мы создаем маркер, например картину, которую вешаем на стену.

    Что может быть маркером.

    Если мы берем маркеры дополненной реальности, есть несколько систем, которые разрабатываются с начала девяностых годов. Вот ссылка на топик где я подробно описывал маркерные технологии дополненной реальности.
    Вот гравюра Дюрера — носорог. Может ли она быть маркером? Да может.

    Соответственно, как? Вот для этого собственно и существует метод SURF. Вот отличная статья, которая очень хорошо описывает методику поиска устойчивых признаков.

    Если вдумчиво разобраться в методе, посмотреть исходные (раз,два, три) публикации, то появятся такие выводы(подробней об этом в скринкасте):
    1. Метод имеет чувствительность, которую необходимо настраивать.
    2. Метод дает ложные срабатывания.
    3. При построении метода используются эмпирические коэффициенты, которые также нуждаются в подстройке для частного случая.
    4. Метод имеет предпосылки для распаралелливания и оптимизации.

    И самое основное — для использования в законченном приложении дополненной реальности, мало распознать маркер, нужно уметь следить за ним, производить «трекинг» и гасить ложные срабатывания, аноамальные выбросы точек, которые нам может давать 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 и растущего интереса к дополненной реальности, целью выступления было описать метод, поделиться с людьми идеями и мыслями, которые многократно умножаются в процессе обсуждения.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 6

      0
      Спасибо очень интересно. А для распознавания (сравнения) лиц данный метод подойдет?
        0
        Для распознавания лиц данный метод подойдет ограниченно. Вот статья, habrahabr.ru/post/103107/
        где такое описывается. Но в таком виде, как оно там представлено — использовать в реальности не получиться, потому что очень сильно зависит от угла зрения.
          0
          Статью читал, ведь там как раз сравниваются лица. Но до конца так и не разобрался, как сохранить эти особые точки в БД, например.
            0
            В моей статье:

            // Определяем ключевые точки
            surfDetDes(img, ipts, false, 4, 4, 2, 0.001f);

            вот через ipts можно получить структура, которую потом сохранить в БД.
              0
              Ну с библиотекой то понятно, но хочется самому понять как алгоритм работает
                0
                Ну тогда скринкаст — я там довольно подробно постарался объяснить тонкости алгоритма и что это за точки.

        Only users with full accounts can post comments. Log in, please.