8. OpenCV шаг за шагом. Запись видео

1. OpenCV шаг за шагом. Введение.
2. OpenCV шаг за шагом. Установка.
3. OpenCV шаг за шагом. Hello World.
4. OpenCV шаг за шагом. Загрузка картинки.
5. OpenCV шаг за шагом. Вывод видео
6. OpenCV шаг за шагом. Ползунок
7. OpenCV шаг за шагом. Захват видео с камеры
8. OpenCV шаг за шагом. Запись видео

OpenCV предоставляет замечательную возможность не только просматривать видео, но так же и сохранять его в файл.

Для этого необходимо сначала инициализировать структуру редактора с помощью функции cvCreateVideoWriter(), в качестве параметров которой передаются название файла для сохранения видео, четырёх-буквенный код видео-кодека, размер кадра и частоту кадров.
Далее при получении кадра с камеры или очередной картинки из набора изображений — он записывается в файл с помощью функции cvWriteFrame(). И в конце — нужно не забыть освободить редактор функцией cvReleaseVideoWriter().
//
// Программа получает видео с камеры и записывает в avi файл
//

#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	cvNamedWindow("capture");

	// получаем любую подключённую камеру
	CvCapture *capture = cvCreateCameraCapture(CV_CAP_ANY);
	assert(capture!=0);

	const char *filename = "capture.avi";

	// частота кадров
	//double fps = cvGetCaptureProperty (capture, CV_CAP_PROP_FPS);
	double fps = 15;

	// размер картинки
	//CvSize size = cvSize( (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH), (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT));
	CvSize size = cvSize(640, 480);

	CvVideoWriter *writer = cvCreateVideoWriter(filename, CV_FOURCC('X','V','I','D'), fps, size, 0);
	assert(writer!=0);

	IplImage *frame=0;

	while(true){
		// получаем кадр
		frame = cvQueryFrame( capture );

		// сохраняем в файл
		cvWriteFrame(writer, frame);

		// показываем
		cvShowImage("capture", frame);  
		char c = cvWaitKey(1);
		if (c == 27) { // если нажата ESC - выходим
			break;
		}
	}

	// освобождаем ресурсы
	cvReleaseCapture( &capture );
	cvReleaseVideoWriter(&writer);
	cvDestroyWindow("capture");
	return 0;
}


Обратите внимание, что заданный кодек установлен в системе.

CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc, double fps, CvSize frame_size, int is_color CV_DEFAULT(1));
— инициализация записи видео в файл
возвращает указатель на структуру редактора видео-файла:
struct CvVideoWriter
{
    virtual ~CvVideoWriter() {}
    virtual bool writeFrame(const IplImage*) { return false; }
};

filename — имя файл для записи
fourcc — 4-буквенный код кодека для обработки видео, формируется макросом CV_FOURCC:
CV_FOURCC('X','V','I','D') - кодек XviD
CV_FOURCC('P','I','M','1')    = MPEG-1
CV_FOURCC('M','J','P','G')    = motion-jpeg  (does not work well)
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 
CV_FOURCC('U', '2', '6', '3') = H263 
CV_FOURCC('I', '2', '6', '3') = H263I 
CV_FOURCC('F', 'L', 'V', '1') = FLV1 

fps — астота кадров созданного видео потока
frame_size — размер кадра
is_color — определяет сохранять цветное изображение (1) или в градациях серого(0) (пока только под Windows)

CVAPI(int) cvWriteFrame( CvVideoWriter* writer, const IplImage* image );
— записывает/добавляет кадр в видео-файл

writer — указатель на структуру редактора видео-файла.
image — изображение для сохранения

CVAPI(void) cvReleaseVideoWriter( CvVideoWriter** writer );
— закрывает видео-файл
writer — указатель на структуру редактора видео-файла.


Далее: 9. OpenCV шаг за шагом. События от мышки
  • 0
  • 20 июля 2010, 11:49
  • noonv

Комментарии (17)

RSS свернуть / развернуть
+
0
Лучше при инициализации writer последний параметр ставить 1
avatar

Mur

  • 5 ноября 2010, 16:06
+
0
В примере видно, что частота кадров и размер задаются конкретными числами.
Попробовал раскомментировать строку
double fps = cvGetCaptureProperty (capture, CV_CAP_PROP_FPS);

Как я понял, она должна определять действительную частоту кадров (с fps=15 записанное видео у меня получается ускоренным).
Но после этого стало появляться исключение при инициализации редактора.
Вот такой printf:
printf(" fps: %f\n", fps);

сообщает
fps: 0.000000

Значит я неправильно вызываю cvGetCaptureProperty?
Не подскажете, как ей пользоваться правильно?
avatar

Storm

  • 14 ноября 2010, 17:56
+
0
посмотрите исходники OpenCV — скорее всего эта функция просто не отрабатывает
avatar

noonv

  • 14 ноября 2010, 18:44
+
0
Господа, как решить проблему — видеофайл создается, имеет адекватный размер, но не проигрывается никакими плеерами (выдается ошибка — типа недопустимая операция). Пробовал указывать разные кодеки.

Во время записи видео пишется что-то типа такого: «compiler did not align stack variables...» и т.д. что компилятор не может скомпилить libavcodec и это проблема компилятора, а не кодека.

Подскажите, как решить проблему?
компилятор: VS2008, OpenCV 1.1 (так же пробовал с 1.0), OS Win7x64.
avatar

jimm88

  • 21 апреля 2011, 11:12
+
0
думаю, стоит попробовать более свежую версию библиотеки ;)
на данный момент — это 2.2 (в сборе она идёт под 2010-ю студию и чтобы заставить работать её под 2008-й её нужно пересобрать), но можете попробовать и 2.1
avatar

noonv

  • 21 апреля 2011, 12:50
+
0
сам столкнулся с этой проблемой :(
OpenCV 2.1 при попытке записи видео выпадает ошибка:
Compiler did not align stack variables. Libavcodec has been miscompiled
and may be very slow or crash. This is not a bug in libavcodec,
but in the compiler. You may try recompiling using gcc >= 4.2

примечательно, что в OpenCV 2.0 запись отрабатывает на ура :)
avatar

noonv

  • 29 июня 2011, 12:49
+
0
Не получается сохранить видео.
Вчера скопипастил пример, запускаю
OpenCV Error: Unsupported format or combination of formats (cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1.) in CvVideoWriter_FFMPEG::writerFrame, file /home/nefka/Загрузки/opencv/OpenCV-2.2.0/modules/highgui/src/cap_ffmpeg.cpp, line 1076
terminate called after throwing an instance of 'cv::Exception'
what(): /home/nefka/Загрузки/opencv/OpenCV-2.2.0/modules/highgui/src/cap_ffmpeg.cpp:1076: error: (-210) cvWriteFrame() needs images with depth = IPL_DEPTH_8U and nChannels = 1. in function CvVideoWriter_FFMPEG::writerFrame

Аварийный останов

менял
IplImage* frame=0;
на
IplImage* frame=cvCreateImage(size,IPL_DEPTH_8U,1);
не помогает.
Пересобрал ffmpeg и opencv, не помогло. ОС Ubuntu 10.04.
если закомментировать строку
cvWriteFrame(writer, frame);

и увеличить cvWaitKey() с 1 до 33, как впредыдущем прмимере, то видео показывает.
avatar

Nefka

  • 1 июня 2011, 15:56
+
0
Все проблема решена, 18 часов, штук пять кружек кофе, 2 Mur спасибо. Заменил
CvVideoWriter *writer = cvCreateVideoWriter(filename, CV_FOURCC('X','V','I','D'), fps, size, 0);
на
CvVideoWriter *writer = cvCreateVideoWriter(filename, CV_FOURCC('X','V','I','D'), fps, size, 1);
и все заработало
avatar

Nefka

  • 1 июня 2011, 16:02
+
0
:)
avatar

noonv

  • 1 июня 2011, 16:06
+
0
пасиб
avatar

ns5d

  • 19 августа 2012, 10:56
+
0
Господа, я может чего-то не понимаю?..

Если делать, как написал Nefka 1 июня 2011, всё работает… НО!!!

В этом примере: CvCapture *var =…
А во всех предыдущих: CvCapture* var =…

Разница лишь в том, где * стоит после CvCapture, IplImage, char* и т д. Но если в этом примере
все CvCapture *, IplImage * и пр. изменить на CvCapture*, IplImage* и пр., уже ничего не работает, и вылазит ошибка

Compiler did not align stack variables. Libavcodec has been miscompiled
and may be very slow or crash. This is not a bug in libavcodec,
but in the compiler...,

уже упомянутая выше.

Win7 64
OpenCV 2.1

Я просто места себе не могу найти — никак не понимаю, ПОЧЕМУ оно так ((((((

Заранее спасибо

avatar

romik9999

  • 4 сентября 2011, 22:11
+
0
при запуске ругается на
assert(writer!=0);

assertion failed!
program:…
file:
line:62
expension: writer!=0

и три варианта ответа: прервать, повтор, пропустить
если пропустить то картинка с камеры есть но не идет запись
avatar

brutalis

  • 27 января 2013, 19:47
+
0
Работаю в Xcode 5.0
Система Macintosh Маверик (OS X 10.9.2)

Вылетает ошибка

OpenCV Error: Assertion failed (dst.data == dst0.data) in cvCvtColor, file /Users/maksim/Downloads/opencv/modules/imgproc/src/color.cpp, line 4422
libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /Users/maksim/Downloads/opencv/modules/imgproc/src/color.cpp:4422: error: (-215) dst.data == dst0.data in function cvCvtColor

На строчке

cvWriteFrame(writer, frame);

Менял writer как сказал Mur — не помогло
avatar

Maxon

  • 3 апреля 2014, 12:41
+
0
подскажите, какими средствами можно выдать поток сделанный в opencv в виде стрима наружу. любой вариант подойдет.
смысл. на raspberry обработал opencv изображение, а как выдать на веб сервер понять не могу. хотя бы направление подскажите.
например на вход GStreamer как можно из opencv подать. или как проще можно
avatar

businka76

  • 6 декабря 2014, 21:07
+
0
Вероятно, самым простым способом будет передавать картинку в формате MJPEG (Motion JPEG) — это когда, каждый кадр представляет собой изображение в формате JPEG.
Для сжатия можно использовать cvEncodeImage(), а далее просто
открываем серверный сокет и подключившимся клиентам отдаём заголовок и картинку.
За основу можно взять тот же MJPG-streamer, написанный на C.

PS вопросы, напрямую не относящиеся к теме топиков лучше задавать на форуме.
avatar

noonv

  • 8 декабря 2014, 10:11
+
+1
Спасибо за ответ. удалось получить результат. Создал ветку на форуме
avatar

businka76

  • 8 декабря 2014, 23:05
+
0
Все работает хорошо(debian 8 qt). Пишет 640х480 (avi). А что надо сделать, чтобы писало в 1280х720? просто поставить cvSize(1280, 720) не записывает(создает файл, но не пишет).
avatar

ilya0606

  • 11 октября 2016, 07:27

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.