Опубликован: 20.08.2013 | Уровень: для всех | Доступ: платный | ВУЗ: Новосибирский Государственный Университет
Самостоятельная работа 1:

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

< Лекция 5 || Самостоятельная работа 1: 12345678910 || Самостоятельная работа 2 >

5. Разработка приложения для демонстрации базовых операций работы с видеоданными

5.1. Задача детектирования лиц

Задача детектирования лиц (face detection) на изображении во многих случаях является подзадачей при решении более сложных проблем (например, распознавания лица или определения выражения лица). Тем не менее, информация о присутствии лиц и их местоположении может быть полезна для таких приложений, как охранные системы и системы детектирования лиц в фото- и видеотехнике [16].

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

Задача автоматического определения положения лиц является достаточно сложной, и этому существует несколько объяснений:

  1. Значительное расхождение внешнего вида и формы лица.
  2. Различие изображения лица при изменении ориентации относительно камеры.
  3. Вариативность выражения лица.
  4. Возможность перекрытия полного изображения, например, прядью волос или полями шляпы.
  5. Другие субъективные факторы такие, как освещенность, искажения, которые вносятся оптикой.

5.2. Базовые операции

5.2.1. Загрузка видео из файла, перехват видеопотока с камеры

Работа с видео в OpenCV организована посредством использования функционала класса VideoCapture. Чтобы открыть видеофайл или поток видео с конкретного устройства, достаточно создать объект указанного класса, вызвав конструктор по умолчанию и метод open, которому на вход передать название файла или идентификатор устройства соответственно.

VideoCapture(); 
virtual bool open(const string& filename); 
virtual bool open(int device);       
      

Альтернативный вариант – в конструктор класса передать название видеофайла или идентификатор устройства.

VideoCapture(const string& filename); 
VideoCapture(int device);       
      

Для проверки корректности открытия видеопотока, необходимо вызвать метод isOpened. Прототип метода представлен ниже.

virtual bool isOpened() const;       
      

После обработки видеопотока необходимо освободить занятые ресурсы посредством вызова метода release.

virtual void release();       
      
5.2.2. Извлечение кадров видеопотока

Продолжая рассматривать методы работы с видепотоком, обратимся к операции получения следующего кадра. Для этого необходимо последовательно вызвать методы grab и retrieve, передав второму методу в качестве входного параметра объект типа Mat, куда будет записан кадр видео.

virtual bool grab(); 
virtual bool retrieve(Mat& image, int channel=0);       
      

Другой вариант получения следующего кадра видеопотока – это использовать перегруженную операцию перенаправления потока ввода. Прототип данной операции приведен ниже.

virtual VideoCapture& operator >> (Mat& image);       
      
5.2.3. Получение и установка свойств видеофайла

В некоторых случаях требуется получить/установить свойства видео. Для этого достаточно использовать методы get/set, реализованные в классе VideoCapture. Метод set позволяет установить свойство с идентификатором propId, равным значению value. Метод get возвращает значение свойства propId.

virtual bool set(int propId, double value); 
virtual double get(int propId);       
      

Перечислим возможные значения идентификаторов свойств.

  • CV_CAP_PROP_POS_MSEC – текущая позиция кадра в треке в миллисекундах;
  • CV_CAP_PROP_POS_FRAMES – индекс следующего кадра, который будет извлекаться из видеопотока (индексация начинается от 0);
  • CV_CAP_PROP_POS_AVI_RATIO – относительная позиция в видеофайле (0 – начало трека, 1 – конец трека)
  • CV_CAP_PROP_FRAME_WIDTH – ширина кадра;
  • CV_CAP_PROP_FRAME_HEIGHT – высота кадра;
  • CV_CAP_PROP_FPS – количество кадров, отображаемых в секунду;
  • CV_CAP_PROP_FOURCC – код кодека;
  • CV_CAP_PROP_FRAME_COUNT – количество кадров в видео;
  • CV_CAP_PROP_FORMAT – формат объекта типа Mat, который возвращается методом retrieve;
  • CV_CAP_PROP_MODE – значение, которое определяет текущий режим захвата;
  • CV_CAP_PROP_BRIGHTNESS – яркость изображения (только для камер);
  • CV_CAP_PROP_CONTRAST – контрастность изображения (только для камер);
  • CV_CAP_PROP_SATURATION – насыщенность изображения (только для камер);
  • CV_CAP_PROP_HUE – тон изображения (только для камер);
  • CV_CAP_PROP_GAIN – усиление изображение (только для камер);
  • CV_CAP_PROP_EXPOSURE – выдержка (только для камер);
  • CV_CAP_PROP_CONVERT_RGB – булев флаг, который указывает на необходимость конвертации изображения в RGB формат.
5.2.4. Сохранение кадров видеопотока в видеофайл

При разработке реальных приложений очень часто возникают ситуации, когда необходимо перехватывать видеопоток с камеры и сохранять его или обработанную копию в видеофайл. Разработчики библиотеки OpenCV обеспечивают данную возможность посредством предоставления класса VideoWriter. По структуре и именованию методов класс похож на VideoCapture. Чтобы открыть поток на запись можно создать объект указанного класса, используя конструктор по умолчанию, как следствие, для открытия потока необходимо вызвать метод open.

VideoWriter(); 
virtual bool open(const string& filename, int fourcc, 
    double fps, Size frameSize, 
    bool isColor=true);       
      

Другой вариант – это вызов конструктора с параметрами, который аналогично методу open принимает на вход название видеофайла для записи filename, идентификатор кодека сжатия fourcc, количество кадров в секунду fps и размер кадра frameSize. Дополнительно присутствует параметр по умолчанию isColor, который определяет формат записи (цветное видео или видео в оттенках серого).

VideoWriter(const string& filename, int fourcc, 
  double fps, Size frameSize, bool isColor=true);       
      

По аналогии с интерфейсом класса VideoCapture имеется метод isOpened, позволяющий определить, открыт ли поток записи или нет.

virtual bool isOpened() const;       
      

Для записи кадра в видеофайл используется перегруженная операция перенаправления потока вывода.

virtual VideoWriter& operator << (const Mat& image);       
      
5.2.5. Детектирование лиц на изображении с использованием классификатора Хаара

Доступ к реализации каскадного классификатора Хаара осуществляется посредством работы с объектами класса CascadeClassifier. В данном разделе рассмотрим некоторые методы указанного класса, которые позволяют выполнять поиск лиц. При этом опустим этап тренировки классификатора, т.к. это достаточно длительная по времени и вычислительно трудоемкая процедура. В состав установленного пакета файлов библиотеки OpenCV уже входят натренированные модели3 Модели можно найти в директории OpenCV-2.4.2\opencv\data\haarcascades. .

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

CascadeClassifier(); 
bool load(const string& filename);       
      

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

CascadeClassifier(const string& filename);       
      

Чтобы найти лица разного масштаба на изображении, необходимо вызвать метод detectMultiScale.

void detectMultiScale(const Mat& image, 
    vector<Rect>& objects, 
    double scaleFactor=1.1, 
    int minNeighbors=3, 
    int flags=0, Size minSize=Size());       
      

Рассмотрим параметры метода. Параметр image – это изображение в оттенках серого (типа CV_8U), на котором необходимо продетектировать лица и записать окаймляющие прямоугольники в вектор objects. scaleFactor представляет собой коэффициент масштабирования, который определяет, во сколько раз будет уменьшено изображение на каждом масштабе. Параметр minNeighbors является параметром алгоритма и определяет интенсивность обнаружения лица в заданной позиции, что позволяет отсекать одиночные срабатывания детектора, которые с большой вероятностью являются ложными, и объединять в единую сущность срабатывания, близкие по расположению. В текущей реализации классификатора значение flags не используется и присутствует для совместимости со старым интерфейсом. Параметр size определяет минимальный размер возможного объекта.

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 || Самостоятельная работа 1: 12345678910 || Самостоятельная работа 2 >
Александра Максимова
Александра Максимова

При прохождении теста 1 в нем оказались вопросы, который во-первых в 1 лекции не рассматривались, во-вторых, оказалось, что вопрос был рассмаотрен в самостоятельно работе №2. Это значит, что их нужно выполнить перед прохождением теста? или это ошибка?
 

Алена Борисова
Алена Борисова

В лекции по обработке полутоновых изображений (http://www.intuit.ru/studies/courses/10621/1105/lecture/17979?page=2) увидела следующий фильтр:


    \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 2 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array} - \frac{1}{9} \begin{array}{|c|c|c|}
    \hline \\
    0 & 0 & 0 \\
    \hline \\
    0 & 1 & 0 \\
    \hline \\
    0 & 0 & 0 \\
    \hline 
    \end{array}

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

Что вижу я в конструкции фильтра (скорее всего ошибочно): F(x, y) = 2 * I(x, y) - 1/9 I(x, y) = 17/9 * I(x, y), где F(x, y) - яркость отфильтрованного пикселя, а I(x, y) - яркость исходного пикселя с координатами (x, y). Что означает обычное повышение яркости изображения, при этом без учета соседних пикселей (так как их множители равны 0).

Объясните, пожалуйста, как данный фильтр может повышать четкость изображения?

Сергей Кротов
Сергей Кротов
Россия
Дмитрий Донсков
Дмитрий Донсков
Россия, Москва, Московский Авиационный Институт