利用OpenCV进行【视频的读取】与【保存视频文件或者图像】源码!~
为了能够更好的支持AVI视频的读取,请安装K-Lite Codec Pack Full 3.9.3 Beta
下载地址:http://dl.pconline.com.cn/html_2/1/124/id=6563&pn=0.html
#include <afx.h>
#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std;
/
//作者:Flobert_Young
//日期:2008-05-22
//说明:
// 需要配置OpenCV的开发环境,并且一定要确保当前Project里加入了cv.lib cxcore.lib highgui.lib库
//链接错误解决方法:
// 编译时出现unresolved external symbol __endthreadex 的处理方法
// 菜单 Project->Settings... 在 C/C++ 页,
// 在 Category 下拉框里选择 Code Generation,
// 然后在 Use run-time library 里选择
// Debug Multithreaded ( Debug 版本时用 )
// 或者 Multithreaded ( release 版本时用).
/
enum CaptureCase
{
CAP_FROM_CAM = 0,
CAP_FROM_VIDEO = 1,
};
enum PlayVideoCase
{
FRAME_BY_FRAME = 0,
FRAME_BY_INDEX = 1,
};
//
//函数声明
int FrameByFrame(CvVideoWriter * pVideoWriter,IplImage *pFrame,bool bSave,
CvCapture * pCapture,char *pVideoSaveName,int nWaitKeyTime);
int FrameByIndex(CvCapture * pCapture,IplImage *pFrame,
int cap_prop,int cap_prop_value,
CString strSaveImagePath);
//
//主函数部分
int main()
{
int ret = 0;
bool bErr = 0;
bool bSave = 0; //0 - 不保存视频文件;1 - 保存视频文件
CaptureCase cap_case = CAP_FROM_VIDEO; //设置成从视频文件中获取图像
PlayVideoCase play_case = FRAME_BY_FRAME; //设置成一帧一帧的播放视频文件
int nWaitKeyTime = 40; //显示图像所间隔的时间,以“毫秒”为单位
//
//变量声明
CvCapture * pCapture = NULL; //用于在视频中捕获图像
char szVideoFileName[] = "C://电影.AVI"; //!将打开的视频文件名设置成"C://1.mpg"
char szVideoSaveName[] = "C://VideoSave.avi"; //!将保存视频文件的名字设置成"C://VideoSave.avi"
CString strSaveImagePath = "C://"; //!保存图片的目录名
CvVideoWriter * pVideoWriter = NULL; //用于保存视频文件
IplImage * pFrame = NULL;
IplImage * pImage = NULL;
switch(cap_case)
{
case CAP_FROM_CAM:
//函数cvCaptureFromCAM()参数说明:
//要使用的摄像头索引。如果只有一个摄像头或者用哪个摄像头也无所谓,那使用参数-1应该便可以。
pCapture = cvCaptureFromCAM(-1); //和函数cvCreateCameraCapture()有什么区别???
if(NULL==pCapture) //打开摄像头
{
cout<<"ERROR: 摄像头读取失败!"<<endl;
bErr = 1;
}
break;
case CAP_FROM_VIDEO: //打开视频文件
pCapture = cvCaptureFromFile(szVideoFileName); //和函数cvCreateFileCapture()有什么区别???
if(NULL==pCapture)
{
cout<<"ERROR: 视频文件读取失败!"<<endl;
bErr = 1;
}
break;
}
if(!bErr)
{
switch(play_case)
{
case FRAME_BY_FRAME:
FrameByFrame(pVideoWriter,pFrame,bSave,pCapture,szVideoFileName,nWaitKeyTime);
break;
case FRAME_BY_INDEX:
//在窗口上显示视频的61%部分的那一帧图像
int cap_prop_value = 61;
FrameByIndex(pCapture,pFrame,CV_CAP_PROP_POS_AVI_RATIO,cap_prop_value,strSaveImagePath);
break;
}
}
char ch;
cin>>ch;
return ret;
}
int FrameByFrame(CvVideoWriter * pVideoWriter,IplImage *pFrame,bool bSave,
CvCapture * pCapture,char *pVideoSaveName,int nWaitKeyTime)
{
int ret = 0;
/****************************************/
///
//1.逐帧读取视频
int nCurFrameIndex = 0;
cvNamedWindow("Frame_By_Frame",1);
//在图像窗口左上角显示“Current Frame: **”字符串
CString strFrameString;
CvFont font;
cvInitFont( &font,CV_FONT_HERSHEY_SIMPLEX,0.5,0.5,0,2,8 );
//创建视频文件写入器
//第二个参数fourcc - 四个字符用来表示压缩帧的codec
//例如,CV_FOURCC('P','I','M','1')是MPEG-1 codec,
//CV_FOURCC('M','J','P','G')是motion-jpeg codec等。
//在Win32下,如果传入参数-1,可以从一个对话框中选择压缩方法和压缩参数。
//这里是按20帧/s进行写入视频文件的,但是当右键"C://VideoSave.avi"属性 -> 摘要,
//发现“持续时间: 0:00:02 帧速率: 500帧/秒”???
//如果改成30帧/s,则发现属性改为“持续时间: 0:00:01 帧速率: 750帧/秒”???
if(1==bSave)
{
pVideoWriter = cvCreateVideoWriter(pVideoSaveName,-1,20,cvSize(640,480),1);
}
if((NULL!=pVideoWriter&&bSave)||(!bSave))
{
while(pFrame = cvQueryFrame(pCapture))
{
if(1==bSave)
{
//将获取的视频文件一帧一帧的写入要保存的视频文件中
cvWriteFrame(pVideoWriter,pFrame);
}
nCurFrameIndex++;
strFrameString.Format("Current Frame: %d",nCurFrameIndex);
cvPutText( pFrame,strFrameString,cvPoint( 5,pFrame->height-15 ),&font,cvScalar( 0,255,0 ) );
cvShowImage("Frame_By_Frame",pFrame);
if(0==bSave) //如果是保存视频时,则加快显示速度
{
cvWaitKey(nWaitKeyTime);
}
else
{
cvWaitKey(10); //如果选择保存视频时,好像不能够正常显示图像???
}
}
if(1==bSave)
{
//释放视频写入器
cvReleaseVideoWriter(&pVideoWriter);
}
cvDestroyWindow("Frame_By_Frame");
cvReleaseCapture(&pCapture);
}
else
{
cout<<"ERROR:创建CvVideoWriter * 失败!"<<endl;
}
/****************************************/
ret = 1;
return ret;
}
int FrameByIndex(CvCapture * pCapture,IplImage *pFrame,int cap_prop,int cap_prop_value,
CString strSaveImagePath)
{
int ret = 0;
/****************************************/
///
//2.读取第i帧视频
cvNamedWindow("FrameIndex_i",1);
//目前这个函数对视频文件只支持:
//CV_CAP_PROP_POS_MSEC, CV_CAP_PROP_POS_FRAMES, CV_CAP_PROP_POS_AVI_RATIO
switch(cap_prop)
{
case CV_CAP_PROP_POS_MSEC:
//读取视频中第cap_prop_value秒的图像
cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_MSEC,cap_prop_value);
break;
case CV_CAP_PROP_POS_FRAMES:
//读取视频中第cap_prop_value帧的图像
cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_FRAMES,cap_prop_value);
break;
case CV_CAP_PROP_POS_AVI_RATIO:
//读取视频中cap_prop_value%处的图像
double ratio = cap_prop_value/100.0; //100.0是为了将除法的结果转化成“浮点型”
cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_AVI_RATIO,ratio);
break;
}
if(pFrame = cvQueryFrame(pCapture))
{
//保存当前图像
CString strSaveImageName;
CString strTmp;
strTmp.Format("SaveImage_%d.bmp",cap_prop_value);
strSaveImageName = strSaveImagePath + strTmp;
cvSaveImage(strSaveImageName,pFrame);
cvShowImage("FrameIndex_i",pFrame);
cvWaitKey(-1);
}
cvDestroyWindow("FrameIndex_i");
cvReleaseCapture(&pCapture);
/****************************************/
ret = 1;
return ret;
}