CA3 (Видеопроцессинг)

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

Работа программы начинается с объявления экземпляра класса VideoCapture(), который предоставляет нам доступ к видео-файлу или любому другому видеопотоку (если дать ему «0» или «/dev/video0», то видео будет забираться с вашей веб-камеры, если она есть). Далее в бесконечном цикле мы последовательно получаем кадры видео один за другим с помощью функции cap >> frame, которая возвращает указатель на уже знакомую нам структуру картинки IplImage.
Показываем кадр в окошке, а затем при помощи функции WaitKey ждём 33 миллисекунды и затем цикл продолжается, если не нажата клавиша ESC.
33 выбрано не случайно — т.к. эта задержка даёт возможность просмотра 30 кадров в секунду.

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

  1. Выделение контуров (проект contour_extraction)
  2. «Замыливание» (проект blur)

Задание

Задание творческое. В исходниках OpenCV-4.0.1 есть папка samples/cpp или samples/python. Их можно посмотреть и в вебе. Внутри очень большое число сэмплов, в большинстве из которых вы найдете волшебные слова VideoCapture и бесконечный цикл while(true) со считыванием кадра cap >> frame. Это значит, что пример вам подходит, переделок будет минимум скорее всего.

Вы можете создать отдельную папку для тестов, куда скопируете вашего подопечного и соберете. Если все прошло хорошо и программа запускается и делает что-то интересное (если изначально не понятно по названию), то предлагаю вам перенести ее функционал в ваш сэмпл с blur. Т.е. сделать GaussianBlur(), а потом уже поставить нужную функцию.

Пример выполнения задания

Для понимания пример, как бы это делал я, т.к. подводные камни все же есть и не все очевидны.

Я изначально копирую папку blur (ведь там готовая сборочная система под OpenCV) и называю новую папку-копию test. Заглянув в sample/cpp я вижу файл smiledetect.cpp и думаю «Россия — для грустных!». Это то, что мне надо! Программа будущего робота контроля за улыбками. Я забираю файл smiledetect.cpp в папку test, откуда параллельно убираю ненужный blur.cpp. В файле сборки не забываю заменить blur.cpp на новый smiledetect.cpp и меняю для удобства название выходного файла в последних 2 строчках с app на smiledetect. Все, теперь должно собираться (выполняем в консоли в текущей папке):

mkdir release

cd release

cmake ..

make

<в текущей директории release должен появиться исполняемый файл>

Внимательно следите за тем, как нужно запускать файл. Т.е. не просто «./smile_detect», а, скажем, «./smile_detect video.mp4». Хотя, о неправильном запуске сэмпл-программы вам сообщат — в них это предусмотрено почти всегда.

Заглянув в smiledetect.cpp я понял, что весь поиск улыбки производится в функции

void detectAndDraw( Mat& img, CascadeClassifier& cascade,
CascadeClassifier& nestedCascade,
double scale, bool tryflip) { …… }

я полностью забираю ее в свою программу. Так же как и в примере, размещая ее ниже чем основная функция main не забывая ее объявить выше (строчка 24 в smiledetect.cpp).
Это сложный пример, т.к. теперь нужно эту функцию использовать в моем коде, нужно передать ей все ее параметры-аргументы. Я смотрю, что в примере загружают в нее и понимаю, что это обученные каскады (мы уже использовали каскады в примере с поиском лица — тут еще есть параметр nestedCascade, который представляет собой отдельный каскад поиска улыбок). Чтобы не мучать свою программу лишними строками выбора каскадов я просто говорю функции, что есть у меня такие каскады и они рядом с запускаемым файлом.

Кроме того, scale (масштаб) я выставляю в 1, а параметр tryflip (перевернуть детектор и попробовать найти отрицательную улыбку) выставлю в 0 за ненадобностью.

Пример размещения файлов каскадов

После этого я помещаю в код функцию detectAndDraw аккурат за функцией blur.

GaussianBlur(image, image_blurred, Size(slider, slider), sigma);
imshow("Blurred Image", image_blurred);
detectAndDraw(image_blurred, "haarcascade_frontalface_alt.xml", "haarcascade_smile.xml", 1, 0 );
imshow("Smile Detector", image_blurred);

В результате выполнения программы у меня теперь выскакивает 2 окна — одно замыленное, а второе — результат поиска улыбок на размытом экране. Теперь я могу проводить целое исследование на тему «Зависимость результативности работы детектора улыбок на основе HOG от степени размытия кадра».

Да, этот пример достаточно сложный. Вы можете повторить его вслед за мной, но лучше поищите примеры попроще, заодно будете понимать, что в принципе умеет OpenCV.

Оставьте комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *