OpenCV 视频与图片序列相互转换 VideoWriter生成视频流

OpenCV学习笔记(四十七)——VideoWriter生成视频流highgui

http://blog.csdn.net/yang_xian521/article/details/7440190

标签: codecflv工具imagevideoavi
  29107人阅读  评论(24)  收藏  举报
  分类:
 

首先要先纠正个误区,我见有人用OpenCV做多媒体开发,真的是很搞笑,OpenCV这东西再强大,这方面也不行的,之所以把视频读取写入这部分做的强大一些,也是为了方便大家做视频处理的时候方便些,而且这部分也是基于vfw和ffmpeg二次开发的,功能还是很弱的。一定要记住一点,OpenCV是一个强大的计算机视觉库,而不是视频流编码器或者解码器。希望大家不要走入这个误区,可以把这部分简单单独看待。目前,OpenCV只支持avi的格式,而且生成的视频文件不能大于2GB,而且不能添加音频。如果你想突破这些限制,我建议你最好还是看看ffMpeg,而不是浪费时间在OpenCV上。不过也可以利用视频后期合成工具制作。闲言少叙,进入重点VideoWriter类。

这个类是highgui交互很重要的一个工具类,可以方便我们容易的将图片序列保存成视频文件。类内成员函数有构造函数,open,isOpened,write(也可以用<<),使用还是很简单的。

使用很简单,先调用构造函数确定文件的名称,格式,帧率,帧大小,是否彩色。其中格式作为第二个参数,OpenCV提供的格式是未经过压缩的,目前支持的格式如下:

CV_FOURCC('P', 'I', 'M', '1') = MPEG-1 codec

CV_FOURCC('M', 'J', 'P', 'G') = motion-jpeg codec
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec 
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec 
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec 
CV_FOURCC('U', '2', '6', '3') = H263 codec 
CV_FOURCC('I', '2', '6', '3') = H263I codec 

CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

然后就<<不停的把image传进去就行啦,太简单了,我都不好意思写了。上代码:

[cpp]  view plain  copy
  1. #include <opencv2/core/core.hpp>  
  2. #include <opencv2/highgui/highgui.hpp>  
  3.   
  4. using namespace cv;  
  5.   
  6. void main()  
  7. {  
  8.     VideoCapture capture(0);  
  9.     VideoWriter writer("VideoTest.avi", CV_FOURCC('M''J''P''G'), 25.0, Size(640, 480));  
  10.     Mat frame;  
  11.       
  12.     while (capture.isOpened())  
  13.     {  
  14.         capture >> frame;  
  15.         writer << frame;  
  16.         imshow("video", frame);  
  17.         if (cvWaitKey(20) == 27)  
  18.         {  
  19.             break;  
  20.         }  
  21.     }  
  22. }  




OpenCV 视频与图片序列相互转换  http://www.cnblogs.com/yingying0907/archive/2012/08/11/2633426.html

我们在计算机视觉相关的实验中都需要视频与图片序列之间相互转换,在平时的实验中,经常需要将视频保存为一帧一帧的图片,以获取实验结果;另一方面,很多标准的算法测试数据库都是图片序列(文件名以帧号+图片扩展名),我们可能需要将其转换为视频,因此视频与图片之间的转换是很常见的操作。在网上找到比较好的测试程序,方面将其封装为函数,方便调用;另一方面,视频转图片可以任意设定图片输出目录,函数会自动创建相关目录;图片序列转视频可以设定更多的参数,也就可以更好的控制,而且可以自行设定视频输出的目录,函数自动检测并创建相关目录。适合windows平台+OpenCV;

代码如下:

复制代码
  1 // ImgToVideo_test.cpp : Defines the entry point for the console application.
  2 //
  3 
  4 #include "stdAfx.h"
  5 #include <cv.h>
  6 #include <highgui.h>
  7 #include <iostream>
  8 #include <direct.h>//for mk_dir
  9 #include <io.h>//for _acess()
 10 #include <string>
 11 
 12 int recursive_mkdir( char *dir );//创建多级目录
 13 int ImageToVideo(char* outDir,char* videoName,char* inputDir,int startFrame,int endFrame, int imgW,
 14     int imgH,char* imgExt,double fps,int isColor,int fourcc);//图片序列转化为视频
 15 int  VideoToImage(char* videoName,char* outDir,char* imgExt,int maxFrameCount);//视频转化为图片序列
 16 
 17 
 18  int main(int argc, char** argv)
 19  {
 20       //图片转视频F:\carrdisp_test\origin
 21       char* inputDir="F:\\carrdisp_test1\\colorfore\\";
 22       char* videoName="carrdisp_clofr.avi";
 23       char* outDir="F:\\carrdisp_test1\\colorfore\\";
 24      int frames=ImageToVideo(outDir,videoName,inputDir,2,308,448,336,"_Fr.jpg",24,1,CV_FOURCC('X','V','I','D'));
 25      std::cout<<"total frames "<<frames<<" have been write to video."<<std::endl;
 26       int p;
 27       std::cin>>p;
 28 
 29     return 0;
 30  }
 31 
 32  //将图片序列转换为视频,返回视频帧数
 33 int ImageToVideo(char* outDir,char* videoName,char* inputDir,int startFrame,int endFrame, int imgW,int imgH,char* imgExt,double fps=24,int isColor=1,int fourcc=CV_FOURCC('X','V','I','D'))
 34 {       
 35         //判断输入文件夹是否存在
 36          if (_access(inputDir,0)==-1)
 37          {
 38     std::cout<<"the input directory does not exist!"<<std::endl;
 39     return 0;
 40          }
 41    //判断输出文件夹是否创建 若没有则创建;若为NULL则默认当前工作目录
 42    char fullVideoName[255];//输出视频的完整文件名:路径+文件名
 43          strcpy_s(fullVideoName,"");
 44    if (outDir==NULL)
 45    {
 46     sprintf_s(fullVideoName,"%s",videoName);//把videoName打印成一个字符串保存在fullVideoName 中 
 47    }
 48    else
 49    {
 50         if (_access(outDir,0)==-1)
 51            {
 52                            recursive_mkdir(outDir);
 53            }
 54       sprintf_s(fullVideoName,"%s%s",outDir,videoName);//将字符串outDir和videoName连接起来,打印,保存在fullVideoName中
 55    }
 56           int frameCount=0;
 57     CvVideoWriter *pWriter=NULL;
 58     CvSize size=cvSize(imgW,imgH);
 59     pWriter=cvCreateVideoWriter(videoName,fourcc,fps,size,isColor);//CREATE WRITER
 60         
 61     IplImage *pImg=NULL;
 62     char cur_fn[255];//表示某张图片的路径
 63     while(startFrame<=endFrame)
 64     {
 65      strcpy_s(cur_fn,"");
 66      sprintf_s(cur_fn,"%s%d%s",inputDir,startFrame,imgExt);//need to change  
 67      pImg=cvLoadImage(cur_fn,isColor);
 68      if (!pImg)    
 69      {
 70       std::cout<<"can't open an image file"<<std::endl;
 71       return frameCount;
 72      }
 73      cvWriteFrame(pWriter,pImg);
 74      cvWaitKey(1);
 75      std::cout<<"Write frame "<<startFrame<<std::endl;
 76      startFrame++;
 77      cvReleaseImage(&pImg);
 78      frameCount++;
 79     }
 80     cvReleaseVideoWriter(&pWriter);
 81     rename(videoName,fullVideoName);//移动文件到指定文件夹
 82     return  frameCount;
 83 }
 84 //将视频转换为图片序列 返回由视频分解得到的图片总帧数 目前OpenCV只支持AVI格式 因此使用之前需要
 85 //将视频转化问AVI格式
 86 
 87 int  VideoToImage(char* videoName,char* outDir,char* imgExt,int maxFrameCount)
 88 {
 89  CvCapture *cap= cvCaptureFromFile(videoName);
 90  if (cap==NULL)
 91  {
 92   return 0;
 93  }
 94    //保存图片的文件夹路径一定要有,因为OpenCV不会自动创建文件夹
 95  if (_access(outDir,0)==-1)
 96  {
 97     recursive_mkdir(outDir);
 98     std::cout<<"the ouput directory does not exist, and the have been created autonomously!"<<std::endl;
 99  }
100  char cur_fn[255];//保存当前帧所得图片的文件名
101  IplImage* pImg=NULL;
102  int frame=0;
103  while((pImg=cvQueryFrame(cap))!=NULL&&(frame<maxFrameCount))
104  {               
105   frame++;
106   strcpy_s(cur_fn,"");
107   sprintf_s(cur_fn,"%s%d%s",outDir,frame,imgExt);//这里的设置适合形如 123.jpg 124.jpg的图片序列
108   cvSaveImage(cur_fn,pImg,NULL);
109  }
110  cvReleaseImage(&pImg);
111  cvReleaseCapture(&cap);
112  return frame;
113 }
114  
115  
116 //该函数借鉴了网上资料,自动创建多级目录
117 int recursive_mkdir( char *dir )
118 {
119  //分解路径名E:\\AA\\BB\\CC\\
120  //
121  std::string str = dir;
122  int index = 0;
123  int i = 0;
124  while(1)
125  {
126   std::string::size_type pos = str.find("\\",index);
127   std::string str1;
128   str1 = str.substr(0,pos);
129   if( pos != -1 && i > 0 )
130   {
131    if (_access(str1.c_str(),0)==-1)
132    {
133        _mkdir(str1.c_str());
134    }
135   }
136   if( pos==-1 )
137   {
138    break;
139   }
140   i ++;
141   index = pos+1;
142  }
143  return 0;
144 }
复制代码

上面程序在VS2010+opencv2.3.1+windows XP环境下测试通过,使用时注意设置好开始帧,结束帧,图片格式即可。本人图片目录如:

F:\carrdisp_test1\colorfore\2_Fr.jpg

其中只调用了图片序列写为视频的函数,另一个函数调用方法相似,如下举例:

复制代码
  //视频转图片
   char* videoName1="E:\\VIDEOS\\TEST\\Videos\\woman.avi";
  char* outDir1="E:\\VIDEOS\\TEST\\Sequences\\WoemenSequence\\";
  int images=VideoToImage(videoName1,outDir1,".jpg",200);
  std::cout<<"total frames have been extracted from video."<<std::endl;
  int p;
  std::cin>>p;
复制代码

感谢资源提供:http://blog.sina.com.cn/s/blog_4b0020f301011yqr.html

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值