今天学习了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);//创建视频写入器VideoWriterchar 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;
}