常見的視頻跟蹤數據庫,如:
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’)等,可能會與某視頻後綴名不匹配,造成視頻編解碼問題,無法讀取。