opencv进行图像序列与视频的转换

常见的视频跟踪数据库,如:

Visual Tracking Benchmark:http://cvlab.hanyang.ac.kr/tracker_benchmark/datasets.html,给出的跟踪算法测试视频多为图片序列,附加待跟踪目标在每一帧视频中的标定位置,即groundtruth,我们可以利用opencv进行视频与图像序列间的转换,由于opencv不会自动创建目录,所以整个程序分为3个部分,多级目录的自动建立,视频转图片序列函数,图片序列转视频函数。

int recursive_mkdir( char *dir );//自动创建多级目录
int ImageToVideo(char* outDir,char* videoName,char* inputDir,int startFrame,int endFrame, int imgW,
    int imgH,char* imgExt,double fps,int isColor,int fourcc);//图片序列转化为视频
int  VideoToImage(char* videoName,char* outDir,char* imgExt,int maxFrameCount);//视频转化为图片序列

自动创建多级目录(从根目录开始):

int recursive_mkdir( char *dir )
{
	 //分解路径名E:\\AA\\BB\\CC\\
	 //
	 std::string str = dir;
	 int index = 0;
	 int i = 0;
	 while(1)
	 {
		  std::string::size_type pos = str.find("\\",index);
		  std::string str1;
		  str1 = str.substr(0,pos);
		  if( pos != -1 && i > 0 )
		  {
			   if (_access(str1.c_str(),0)==-1)
			   {
				   _mkdir(str1.c_str());
			   }
		  }
		  if( pos==-1 ) break;
		  i ++;
		  index = pos+1;
	 }
	 return 0;
}


图片序列转换为视频:

//将图片序列转换为视频,返回视频帧数(输入输出目录,输入图片长宽,起始帧与结束帧,扩展名等)
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'))
{       
    //判断输入文件夹是否存在
	if (_access(inputDir,0)==-1)
	{
		std::cout<<"the input directory does not exist!"<<std::endl;
		return 0;
	}
    //判断输出文件夹是否创建 若没有则创建;若为NULL则默认当前工作目录
    char fullVideoName[255];//输出视频的完整文件名:路径+文件名
    strcpy_s(fullVideoName,"");
	if (outDir==NULL)
	{
		sprintf_s(fullVideoName,"%s",videoName);//把videoName打印成一个字符串保存在fullVideoName 中 
	}
	else
	{
		if (_access(outDir,0)==-1)
			{
				recursive_mkdir(outDir);
			}
		sprintf_s(fullVideoName,"%s%s",outDir,videoName);//将字符串outDir和videoName连接起来,打印,保存在fullVideoName中
	}

	int frameCount=0;
	CvVideoWriter *pWriter=NULL;
	CvSize size=cvSize(imgW,imgH);
	pWriter=cvCreateVideoWriter(videoName,fourcc,fps,size,isColor);//CREATE WRITER
        
	IplImage *pImg=NULL;
	char cur_fn[255];//表示某张图片的路径
	const int length=4; //length of the picure name
	
	while(startFrame<=endFrame)
	{
		strcpy_s(cur_fn,"");
		char current_frame[length+1];
		itoa(startFrame,current_frame,10);
		int t=length-strlen(current_frame);
		char current_frame2[length+1];
		sprintf(current_frame2,"%0*d%s", length-strlen(current_frame), 0, current_frame);
		sprintf_s(cur_fn,"%s%s%s",inputDir,current_frame2,imgExt);//need to change  
		pImg=cvLoadImage(cur_fn,isColor);
		if (!pImg)    
		{
		std::cout<<"can't open an image file"<<std::endl;
		return frameCount;
		}
		cvWriteFrame(pWriter,pImg);
		cvWaitKey(1);
		std::cout<<"Write frame "<<startFrame<<std::endl;
		startFrame++;
	
		cvReleaseImage(&pImg);
		frameCount++;
	}
	cvReleaseVideoWriter(&pWriter);
	rename(videoName,fullVideoName);//移动文件到指定文件夹
	return  frameCount;
}


视频转图片序列:

//视频转为图片序列(输入输出目录,扩展名,输出图片总张数)
int  VideoToImage(char* videoName,char* outDir,char* imgExt,int maxFrameCount)
{
	CvCapture *cap= cvCaptureFromFile(videoName);
	if (cap==NULL)
	{
		return 0;
	}
	//保存图片的文件夹路径一定要有,因为OpenCV不会自动创建文件夹
	if (_access(outDir,0)==-1)
	{
		recursive_mkdir(outDir);
		std::cout<<"the ouput directory does not exist, and the have been created autonomously!"<<std::endl;
	}
	char cur_fn[255];//保存当前帧所得图片的文件名
	IplImage* pImg=NULL;
	int frame=0;
	while((pImg=cvQueryFrame(cap))!=NULL&&(frame<maxFrameCount))
	{               
		frame++;
		strcpy_s(cur_fn,"");
		sprintf_s(cur_fn,"%s%d%s",outDir,frame,imgExt);//这里的设置适合形如 123.jpg 124.jpg的图片序列
		cvSaveImage(cur_fn,pImg,NULL);
	}	

	//cvReleaseImage(&pImg);
	cvReleaseCapture(&cap);
	return frame;
}


主函数:

#include <string>
#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <direct.h>//for mk_dir
#include <io.h>//for _acess()
#include <string>
#define ImageToVideoFlag 

int recursive_mkdir( char *dir );//自动创建多级目录
int ImageToVideo(char* outDir,char* videoName,char* inputDir,int startFrame,int endFrame, int imgW,
    int imgH,char* imgExt,double fps,int isColor,int fourcc);//图片序列转化为视频
int  VideoToImage(char* videoName,char* outDir,char* imgExt,int maxFrameCount);//视频转化为图片序列

 int main(int argc, char** argv)
 {	
#ifdef ImageToVideoFlag
	//图片转视频F:\carrdisp_test\origin
	char* inputDir="img_input\\";
	char* videoName="david.mpg";
	char* outDir="E:\\video_output\\";

	//need to change according to your own picture sequences
	int frames=ImageToVideo(outDir,videoName,inputDir,1,770,320,240,".jpg",24,1,CV_FOURCC('X','V','I','D'));
	//int frames=ImageToVideo(outDir,videoName,inputDir,1,770,320,240,".jpg",24,1,CV_FOURCC('M','J','P','G'));
	std::cout<<"total frames "<<frames<<" have been write to video."<<std::endl;
		
	system("pause");
	return 0;
#else
	//视频转图片
	char* videoName1="pedestrian1.mpg";
	char* outDir1="E:\\output_Imgseq\\";
	int images=VideoToImage(videoName1,outDir1,".jpg",200);
	std::cout<<"total frames have been extracted from video."<<std::endl;
	system("pause");
#endif
 }


注意事项:

1.主程序中若是视频转图片序列,请配置自己的视频输入路径(若只是配置文件名,请确保视频文件在程序工程目录中)和图片序列输出路径,输出路径以根目录开始(E:\\)。

2.rename函数将文件移入指定文件夹,但是若文件夹中已有同名文件,则不会移动。

3.图片转视频时,可自行选择输出视频的后缀名,但是注意opencv的视频写入编码CV_FOURCC('X','V','I','D'),CV_FOURCC(’P’,’I’,’M’,’1’),CV_FOURCC(’M’,’J’,’P’,’G’)等,可能会与某视频后缀名不匹配,造成视频编解码问题,无法读取。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值