今天学习了opencv的HighGUI的内容
总结了两个视频读写demo以备以后进行视频处理和识别用
demo1 视频的读取和写入
按顺序读取视频的每一帧。对于读取的每一帧图像,显示在窗口中,然后转化为灰度图像输出到指定的文件中。
运行期间可以按ESC键退出。
还可以用鼠标调整滚动条来动态改变视频的播放位置。滚动条的位置≈想要播放的帧在整个视频中的位置
比如将滚动条调整到如下图所示位置,直接将视频跳转到视频总长度一半的位置开始播放
滚动条的位置≈想要播放的帧在整个视频中的位置 这里之所以是“约等于”,是因为opencv采用的帧定位的函数默认使用的是关键帧的定位方式,导致视频跳转的位置并不准确。
具体可以参见SetCaptureProperty定位不准的原因
另外有个容易出错的地方,创建视频写入器的命令:CvVideoWriter* wrVideo1 = cvCreateVideoWriter(out1, CV_FOURCC('X','V','I','D'), fps1, size1,0);
最后有个参数是0,表示输出的视频文件是灰度的。如果不设置,默认的参数取值为1,代表输出的视频文件是彩色的。如果此时将图像转换成灰度图后输出。运行视频文件是系统会提示错误。
对于这一点的描述可以参见opencv彩色图像转灰度图像失败的原因
demo1的源代码如下:
#include <iostream> #include <cv.h> #include <cxcore.h> #include <highgui.h> // 使用标准命名空间 using namespace std; // 初始化进度条的位置 int g_slider_position1 = 0; //初始化视频捕获器 CvCapture* g_capture1 = NULL; // 定义回调函数用于播放进度的控制 void onTrackbarSlide1( int pos1 ) { cvSetCaptureProperty( g_capture1, CV_CAP_PROP_POS_FRAMES, pos1 ); } int main(int argc, char** argv ) { // 建立播放窗口 cvNamedWindow( "Video Test 1", CV_WINDOW_AUTOSIZE ); // 捕捉视频文件 char video1[] = "yssh.avi"; //创建指定视频文件的捕获器 g_capture1 = cvCreateFileCapture( video1 ); // 读取视频文件的总帧数并显示 int frames1 = (int) cvGetCaptureProperty( g_capture1, CV_CAP_PROP_FRAME_COUNT ); cout << "总帧数 = " << frames1 << endl; // 读取视频文件每秒显示帧数信息 double fps1 = cvGetCaptureProperty( g_capture1, CV_CAP_PROP_FPS ); cout << "fps1 = " << fps1 << endl; //读取视频文件每帧图像大小信息 CvSize size1 = cvSize( (int)cvGetCaptureProperty(g_capture1, CV_CAP_PROP_FRAME_WIDTH), (int)cvGetCaptureProperty(g_capture1, CV_CAP_PROP_FRAME_HEIGHT)); // 建立进度条 if( frames1 != 0 ) cvCreateTrackbar( "Position", "Video Test 1", &g_slider_position1, frames1, onTrackbarSlide1 ); // 创建 VideoWriter char out1[] = "out1.avi"; //CvVideoWriter* wrVideo1 = cvCreateVideoWriter(out1, CV_FOURCC('M','J','P','G'), fps1, size1,0); //创建视频写入器 CvVideoWriter* wrVideo1 = cvCreateVideoWriter(out1, CV_FOURCC('X','V','I','D'), fps1, size1,0); // 记录视频的某一帧 IplImage* frame1; //记录视频某一帧转换后的灰度图像 IplImage* gray1 = cvCreateImage(size1, 8, 1); //读取并播放视频,直至播放结束/主动退出 while( true ) { // 获取源文件的一帧画面 frame1 = cvQueryFrame( g_capture1 ); if( !frame1 ) break; //显示这一帧 cvShowImage( "Video Test 1", frame1 ); // 将当前帧转换为灰度图像 cvCvtColor(frame1 ,gray1, CV_RGB2GRAY); // 保存:将当前帧(灰度图)写入到目标视频文件 cvWriteFrame( wrVideo1, gray1 ); // 若按下 ESC 键,则退出程序 char c = cvWaitKey(33); if( c == 27 ) break; } // 释放内存,关闭窗口 cvReleaseCapture( &g_capture1 ); cvReleaseVideoWriter( &wrVideo1 ); cvDestroyWindow( "Video Test 1" ); return 0; }
demo2 视频等间隔采样
程序按顺序读取视频的每一帧,对于满足固定间隔的帧图像,显示并输入,不满足的直接跳过。
这个demo可以用于等间隔的从视频中抽取图像,以备以后进行视频处理和识别用
demo2的源代码如下:
#include <iostream> #include <cv.h> #include <cxcore.h> #include <highgui.h> // 使用标准命名空间 using namespace std; //初始化视频捕获器 CvCapture* g_capture1 = NULL; int main(int argc, char** argv ) { // 建立播放窗口 cvNamedWindow( "Video Test 1", CV_WINDOW_AUTOSIZE ); // 捕捉视频文件 char video1[] = "yssh.avi"; //创建指定视频文件的捕获器 g_capture1 = cvCreateFileCapture( video1 ); // 读取视频文件的总帧数并显示 int TotalFrames = (int) cvGetCaptureProperty( g_capture1, CV_CAP_PROP_FRAME_COUNT ); cout << "总帧数 = " << TotalFrames << endl; // 读取视频文件每秒显示帧数信息 double fps1 = cvGetCaptureProperty( g_capture1, CV_CAP_PROP_FPS ); cout << "fps1 = " << fps1 << endl; //读取视频文件每帧图像大小信息 CvSize size1 = cvSize( (int)cvGetCaptureProperty(g_capture1, CV_CAP_PROP_FRAME_WIDTH), (int)cvGetCaptureProperty(g_capture1, CV_CAP_PROP_FRAME_HEIGHT)); //CvVideoWriter* wrVideo1 = cvCreateVideoWriter(out1, CV_FOURCC('M','J','P','G'), fps1, size1,0); //创建视频写入器VideoWriter char out1[] = "IntervalOutput.avi"; CvVideoWriter* wrVideo1 = cvCreateVideoWriter(out1, CV_FOURCC('X','V','I','D'), fps1, size1,0); // 记录视频的某一帧 IplImage* frame1; //记录视频某一帧转换后的灰度图像 IplImage* gray1 = cvCreateImage(size1, 8, 1); int position=0; int interval=10; //这里指定一个抽取视频间隔 //读取并播放视频,直至播放结束/主动退出 while( true ) { // 先获取源文件的一帧画面 frame1 = cvQueryFrame( g_capture1 ); if( !frame1 ) //视频读取完毕 break; position=(int)cvGetCaptureProperty( g_capture1, CV_CAP_PROP_POS_FRAMES); if(position%interval!=0) continue; //显示这一帧 cvShowImage( "Video Test 1", frame1 ); // 将当前帧转换为灰度图像 cvCvtColor(frame1 ,gray1, CV_RGB2GRAY); // 保存:将当前帧(灰度图)写入到目标视频文件 cvWriteFrame( wrVideo1, gray1 ); // 若按下 ESC 键,则退出程序 char c = cvWaitKey(33); if( c == 27 ) break; } // 释放内存,关闭窗口 cvReleaseCapture( &g_capture1 ); cvReleaseVideoWriter( &wrVideo1 ); cvDestroyWindow( "Video Test 1" ); return 0; }