从网上看到很多例子都是由已有的视频文件转换成每帧图片,或者是由图片转换成视频。达不到实时转换的效果,总结他们的代码再自己添加一些内容,达到获取视频后直接保存每帧图片。不过尴尬的是竟然遇到360 警告

 

opencv 播放视频总是快放 opencv保存视频每一帧_opencv 播放视频总是快放

opencv 播放视频总是快放 opencv保存视频每一帧_visual studio_02


话不多少,上代码。

#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;
}



这是结果,由一个线激光从上往下移动的实时视频

opencv 播放视频总是快放 opencv保存视频每一帧_visual studio_03