从网上看到很多例子都是由已有的视频文件转换成每帧图片,或者是由图片转换成视频。达不到实时转换的效果,总结他们的代码再自己添加一些内容,达到获取视频后直接保存每帧图片。不过尴尬的是竟然遇到360 警告
话不多少,上代码。
#include <stdio.h>
#include<opencv2/opencv.hpp>
#include<iostream>
#include<direct.h>
#include<io.h>
#include<string>
using namespace std;
using namespace cv;
int recursive_mkdir(char* dir);//recursive:递归,mkdir:DOS命令,建立一个新的子目录,dir:是directory目录的缩写
int VideoToImage( CvCapture* capture,char* outdir,char* imgext,int nowFrameNum);//视频转化为图片序列,nowFrameNum为当前帧数
int main(int argc, char** argv)
{
char* outDir1="D:\\EZ\\Image\\";
VideoCapture cap(0);
CvCapture* capture = cvCaptureFromCAM(0);
if (!cap.isOpened()) // 检查打开是否成功
return -1;
double rate=cap.get(CV_CAP_PROP_FPS);//取得帧速率
int delay=1000/rate;//根据帧速率计算帧之间的等待时间
bool stop (false);
Mat frame;//当前视频帧
namedWindow("Extracted Frame");
int nowFrameNum=0;
while (!stop)
{
if (!cap.read(frame))
break;
waitKey(30);// 延时30ms
imshow("Extracted Frame",frame);
nowFrameNum++; //统计帧数
int images=VideoToImage(capture,outDir1,".jpg",nowFrameNum);
}
return 0;
}
//将视频转换为图片序列 返回由视频分解得到的图片总帧数 目前OpenCV只支持AVI格式 因此使用之前需要
//将视频转化问AVI格式
int VideoToImage(CvCapture* capture,char* outDir,char* imgExt,int nowFrameNum)
{
CvCapture *cap= cvCaptureFromCAM(0);
if (cap==NULL)
{
return 0;
}
//保存图片的文件夹路径一定要有,因为OpenCV不会自动创建文件夹
//int _access(const char* Filename,int Access_Mode) 参数Filename 是访问文件所在的路径名,mode是访问判断模式
//返回0 表示文件在当前路径已存在,返回-1表示该文件在当前路径不存在
if (_access(outDir,0)==-1)
{
recursive_mkdir(outDir);
std::cout<<"输出目录不存在,并已自主创建"<<std::endl;
}
char cur_fn[255];//保存当前帧所得图片的文件名 表示某张图片的绝对路径
IplImage* pImg=NULL;
int frameNUM=0;
//函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并返回这一帧。
while((pImg=cvQueryFrame(cap))!=NULL&&(frameNUM=nowFrameNum))//
{
frameNUM++;
nowFrameNum++;
strcpy_s(cur_fn,"");//strcpy_s是系统的安全函数,strcpy_s是根据'\0'判断源字符串结束的,strcpy_s是以字节为单位的参数,它用来确认缓冲区大小
sprintf_s(cur_fn,"%s%d%s",outDir,frameNUM,imgExt);//这里的设置适合形如 123.jpg 124.jpg的图片序列 sprintf_s将格式化字符串存到缓冲区
cvSaveImage(cur_fn,pImg,NULL);
}
cvReleaseImage(&pImg);
cvReleaseCapture(&cap);
return frameNUM;
}
//该函数借鉴了网上资料,自动创建多级目录
int recursive_mkdir( char *dir )
{
//分解路径名E:\\AA\\BB\\CC\\
//
std::string str = dir;
int index = 0;
int i = 0;
while(1)
{
//size_type由string类类型和vector类类型定义的类型,用以保存任意string对象或vector对象的长度
// find 函数 返回"\\" 在index 中的下标位置
std::string::size_type pos = str.find("\\",index);
std::string str1;
str1 = str.substr(0,pos);//str.substr(a,b)是从a开始截取b个字符。
if( pos != -1 && i > 0 )
{
if (_access(str1.c_str(),0)==-1) // c_str():生成一个const char*指针,指向以空字符终止的数组.这个数组的数据是临时的
{
_mkdir(str1.c_str());
}
}
if( pos==-1 )
{
break;
}
i ++;
index = pos+1;
}
return 0;
}
这是结果,由一个线激光从上往下移动的实时视频