Опубликован: 02.09.2013 | Доступ: свободный | Студентов: 429 / 54 | Длительность: 19:27:00

Самостоятельная работа 1: Сборка и установка библиотеки OpenCV. Использование библиотеки в среде Microsoft Visual Studio

< Лекция 7 || Самостоятельная работа 1: 1234567891011 || Самостоятельная работа 2 >
5.2.6. Отображение прямоугольников на изображении

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

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

Чтобы нарисовать прямоугольник, достаточно вызвать функцию rectangle, которой в качестве входных параметров передать изображения img, координаты левого верхнего pt1 и правого нижнего угла pt2 прямоугольника, а также цвет линии color для RGB- изображения или яркость для изображения в оттенках серого, толщину thickness и тип lineType. Обратите внимание, что если передать отрицательное значение толщины, что соответствует константе CV_FILLED, то будет отрисован прямоугольник, залитый цветом. Параметр shift означает количество дробных бит в координатах точек.

void rectangle(CvArr* img, CvPoint pt1, CvPoint pt2, 
               CvScalar color, int thickness=1,  
               int lineType=8, int shift=0) 
               

Заметим, что наряду с геометрическими примитивами подобным образом можно написать текст на изображении. Для этого достаточно вызвать функцию putText. Подробнее с возможным набором примитивов можно ознакомиться в документации [17].

5.3. Разработка приложения для детектирования лиц на видео

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

const char* helper =    "02_FaceDetection.exe <model_file> [<video>]\n\ 
  \t<model_file> - полное имя файла с моделью\n\ 
  \t<video> - путь до видеофайла (по умолчанию \n\ 
      видеопоток принимается с камеры)\n"; 
      

Создадим функцию main с пустым телом. Перед функцией объявим пару констант DELAY и ESC_KEY. DELAY будем использовать, чтобы зафиксировать время задержки при последовательном отображении кадров видео, ESC_KEY – чтобы обозначить код клавиши Esc, при нажатии которой будет происходить принудительная остановка обработки видеопотока.

#define DELAY 30 
#define ESC_KEY 27 

Обратимся к разработке кода основной функции. Для этого необходимо реализовать следующую последовательность операций:

  1. Разобрать аргументы командной строки, чтобы извлечь полное название файла с моделью лица и при необходимости имя видеофайла.
    char *modelFileName = 0, *videoFileName = 0; 
    if (argc < 2) 
    { 
      printf("%s", helper); 
      return 1; 
    } 
    modelFileName = argv[1]; 
    if (argc > 2) 
    { 
      videoFileName = argv[2]; 
    } 
    
  2. Создать классификатор и загрузить модель.
    // создание классификатора и загрузка модели 
    CascadeClassifier cascade; 
    cascade.load(modelFileName); 
    
  3. Загрузить видео из файла или открыть видеопоток с веб-камеры, если название файла отсутствует в параметрах командной строки.
    // загрузка видеофайла или перехват видеопотока 
    VideoCapture capture; 
    if (videoFileName == 0) 
    { 
      capture.open(0); 
    } 
    else 
    { 
      capture.open(videoFileName); 
    } 
    if (!capture.isOpened()) { 
      printf("Incorrect capture name.\n"); 
      return 1; 
    } 
    
  4. Создать окно для отображения видео.
    const char* winName = "video";   
    // создание окна для отображения видео 
    namedWindow(winName); 
    
  5. Разработать цикл обработки последовательности кадров видепотока. На каждой итерации цикла необходимо конвертировать текущий кадр в оттенки серого, продетектировать лица, отрисовать полученные окаймляющие прямоугольники на изображении и отобразить это изображение. Тело цикла будет выполняться до тех пор, пока не будет достигнут конец трека, либо не будет нажата клавиша Esc.
    char key = -1; 
    Mat image, gray; 
    vector<Rect> objects; 
    // получение кадра видеопотока 
    capture >> image; 
    while (image.data != 0 && key != ESC_KEY) 
    { 
      cvtColor(image, gray, CV_BGR2GRAY); 
      cascade.detectMultiScale(gray, objects); 
      for (i = 0; i < objects.size(); i++) 
      { 
        rectangle(image,  
                    Point(objects[i].x, objects[i].y), 
                    Point(objects[i].x+objects[i].width, 
                         objects[i].y+objects[i].height), 
                    CV_RGB(255, 0, 0), 2); 
      } 
      imshow(winName, image); 
      key = waitKey(DELAY); 
      capture >> image; 
      gray.release(); 
      objects.clear(); 
    } 
    
  6. Освободить ресурсы и закрыть видеопоток.
    capture.release(); 
5.4. Запуск приложения и анализ результатов

Сделаем проект 02_FaceDetection рабочим, выполнив команду контекстного меню Set as StartUp Project…. Скомпилируем и запустим приложение. Будем считать, что видеопоток принимается с веб-камеры, поэтому передадим в качестве параметра командной строки только файл модели. Используем файл haarcascade_frontalface_default.xml.

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

Результат детектирования лиц на одном из кадров  видеопотока

Рис. 8.24. Результат детектирования лиц на одном из кадров видеопотока

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

< Лекция 7 || Самостоятельная работа 1: 1234567891011 || Самостоятельная работа 2 >
Андрей Терёхин
Андрей Терёхин

Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции?

Демянчик Иван
Демянчик Иван

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

" Искомый объект можно описать с помощью фильтра F= \lbrace f_{x',y'},x' \in \lbrace0, ...,w_f \rbrace , y' \in \lbrace 0,...,h_f \rbrace \rbrace "