Небольшой ликбез по поводу OpenCV и работы с видео.
OpenCV поддерживает множество способов захвата и записи видео на всевозможных аппаратных и программных платформах. При этом не используются какие-то его внутренние технологии, а задействуются возможности платформы и установленных на ней библиотек.
На Windows используются родные Video for Windows (vfw) и DirectShow.
Причём vfw используется, начиная с самых ранних версий OpenCV, заканчивая самой последней. Что такое vfw? Это старая технология, корнями уходящяя в Windows 3.1, а то и позже. Декодеры для vfw сейчас почти не пишутся, вероятность проигрывания или записи файла с помощью vfw очень низка. В OpenCV для этого есть функция cvCreateFileCapture_VFW.
DirectShow использовалась в нескольких версиях OpenCV как библиотека VideoInput (см. #ifdef HAVE_VIDEOINPUT CV_CAP_DSHOW, #endif).
На сегодня, DirectShow является предпочтительным средством работы с видео в Windows. Декодеры и кодеры популярных видеокодеков, как правило, оформляют в виде DirectShow фильтров, плейеры используют их, всевозможные грабберы тоже. Что надо сделать, чтобы задействовать DirectShow в OpenCV? Очевидно, сконфигурировать CMake, установив HAVE_VIDEOINPUT в TRUE. Или самому в файле cvconfig.h найти и установить HAVE_VIDEOINPUT.
Теперь перейдём к ffmpeg. Это кроссплатформенная библиотека, которую можно использовать как в Windows, так и в Линуксе. Например, в версии OpenCV 2.3.2 ffmpeg задействуется через opencv_ffmpeg.dll. Её надо кидать в папку к своему exe. И, вроде, всё. Во всяком случае при проигрывании файла *.mp4 именно её функции использовались для декодирования видео, глубже в отладчике я не заглядывал. В предыдущих версиях OpenCV мне приходилось совершать серию шаманских действий для задействования ffmpeg.
Что ещё? А много чего!
XINE = HAVE_XINE + cvCreateFileCapture_XINE
GSTREAMER = HAVE_GSTREAMER + cvCreateCapture_GStreamer
QUICKTIME = HAVE_QUICKTIME + cvCreateFileCapture_QT
AVFOUNDATION = HAVE_AVFOUNDATION + cvCreateFileCapture_AVFoundation
И ещё можно найти, если порыскать по исходникам. То есть различные операционные системы, сторонние библиотеки, аппаратные платформы. Всё это можно найти в документации. Надо лишь установить библиотеки и сконфигурировать CMake. И проиграется практически ЛЮБОЙ файл и захватится видео практически с ЛЮБОЙ камеры.
Теперь посмотрим как оно работает в OpenCV (файл cap.cpp):
/** * Videoreader dispatching method: it tries to find the first * API that can access a given filename. */ CV_IMPL CvCapture * cvCreateFileCapture (const char * filename) { CvCapture * result = 0; if (! result) result = cvCreateFileCapture_FFMPEG_proxy (filename); #ifdef HAVE_VFW if (! result) result = cvCreateFileCapture_VFW (filename); #endif #ifdef HAVE_MSMF if (! result) result = cvCreateFileCapture_MSMF (filename); #endif #ifdef HAVE_XINE if (! result) result = cvCreateFileCapture_XINE (filename); #endif #ifdef HAVE_GSTREAMER if (! result) result = cvCreateCapture_GStreamer (CV_CAP_GSTREAMER_FILE, filename); #endif #if defined(HAVE_QUICKTIME) || defined(HAVE_QTKIT) if (! result) result = cvCreateFileCapture_QT (filename); #endif #ifdef HAVE_AVFOUNDATION if (! result) result = cvCreateFileCapture_AVFoundation (filename); #endif #ifdef HAVE_OPENNI if (! result) result = cvCreateFileCapture_OpenNI (filename); #endif if (! result) result = cvCreateFileCapture_Images (filename); return result; }
То есть, при проигрывании файла OpenCV пытается по очереди найти доступный декодер из тех, с которыми сконфигурирован CMake. Самая первая попытка — создание cvCreateFileCapture_FFMPEG_proxy. Если ffmpeg не находится, то на Windows вызывается функция cvCreateFileCapture_VFW (её на листинге нет, она находится внутри cvCreateFileCapture_FFMPEG_proxy). И дальше по очереди.
Что делать, если файл всё таки не проигрывается? Надо воспользоваться отладчиком. Зайти внутрь функции cvCreateFileCapture и посмотреть какие декодеры вообще задействованы и какие обламываются, хотя должны были бы работать. И, соответственно, посмотреть, почему они обламываются. Это не так сложно.
Например, я попытался проиграть, записанный на телефоне, файл *.mp4. ffmpeg не нашёл opencv_ffmpeg.dll, а vfw не захотел его открывать (что логично). Остальные библиотеки у меня не были задействованы. Поэтому я просто закинул opencv_ffmpeg.dll и всё заработало.
Если бы потребовалось проиграть QuickTime видео, то необходимо было бы найти в документации способ подключения QuickTime и выставить в cvconfig.h HAVE_QUICKTIME (либо сделать это в CMake — так правильней).
По материалам от Nuzhny
По теме
OpenCV шаг за шагом. Захват видео с камеры
Работа с камерой через библиотеку videoInput