opencv目标跟踪:三帧差分法

转载请注明转自:http://blog.csdn.net/ding977921830/article/details/50953895

  网上很多opencv的帧差法资料,但是大都直接调用视频,或者调用摄像头,调用文件夹下的图片库的资料比较少,通过网上整理资料,终于利用opencv按照帧来处理图片。

使用opencv批量读取文件夹下的视频帧批量读取图片

使用opencv批量读取图片,二帧差分法二帧差法

具体代码如下:

//#include "stdAfx.h"

#include <opencv2/core/core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <iostream>
#include <direct.h>//for mk_dir
#include <io.h>//for _acess()

#include <opencv2/imgproc/imgproc.hpp>



#define threshold_diff1 10 //设置简单帧差法阈值
#define threshold_diff2 10 //设置简单帧差法阈值
using namespace cv;
using namespace std;

int recursive_mkdir( char *dir );//创建多级目录

	 ///三帧差分法
	 int main(int argc, char** argv)
 {    批处理读入图片部分参数//
	  char* inputDir="F:\\论文视频库\\视频帧库\\Walking\\";       //一定要加上最后的两个双斜线,输入视频帧的目录
      char* videoName="Walking.avi";                              //输出的视频名字
      char* outDir="F:\\论文视频库\\视频帧库\\Walking\\";         //一定要加上最后的两个双斜线,输出的视频的目录

	  int startFrame = 20;                                        //含义:起始帧
	  int tmpFrame = startFrame;                                  //含义:记录起始帧
	  int endFrame = 412;                                         //含义:起始帧,结束帧 
	  int imgW = 768;                                             //含义:视频帧的宽
	  int imgH = 576;                                             //含义:视频帧的高
	  char* imgExt = ".jpg";                                      //根据图片的性质选择.jpg,.bmp等类型,一定要注意jpg前面那个
	                                                              //点,当时我缺了这个点,浪费了我一晚上的时间才找到问题
	  double fps=24;                                              //帧率
	  int isColor=1;                                              //颜色
	  int fourcc=CV_FOURCC('X','V','I','D');                      //CV_FOURCC('X', 'V', 'I', 'D') 表示是XVID库进行压缩,压缩为MPEG4格式
    
	
	  IplImage *pImg=NULL;
	  IplImage *pImg2=NULL;
	  IplImage *pImg3=NULL;
      char cur_fn[255];											  //表示某张图片的绝对路径
	  char fullVideoName[255];									  //输出视频的完整文件名:路径+文件名
	  int frameCount = startFrame;                                //计算运行到第N帧
	  int frames = 0 ;     //总帧数
      CvSize size=cvSize(imgW,imgH);
	  //帧差法部分参数
	  Mat img_src1,img_src2,img_src3;//3帧法需要3帧图片
      Mat img_dst,gray1,gray2,gray3;
      Mat gray_diff1,gray_diff2,gray_diff;//存储2次相减的图片
      Mat gray;//用来显示前景的
	
        //判断输入文件夹是否存在
         if (_access(inputDir,0)==-1)
         {
           cout<<"the input directory does not exist!"<<endl;
            return 0;
         }
   //判断输出文件夹是否创建 若没有则创建;若为NULL则默认当前工作目录
   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中
   }
        
    while(startFrame<=endFrame)
    {
     strcpy_s(cur_fn,"");
     sprintf_s(cur_fn,"%s%d%s",inputDir,startFrame,imgExt);//need to change  
     pImg=cvLoadImage(cur_fn,isColor);
	 sprintf_s(cur_fn,"%s%d%s",inputDir,startFrame-1,imgExt);//need to change  
     pImg2=cvLoadImage(cur_fn,isColor);
	 sprintf_s(cur_fn,"%s%d%s",inputDir,startFrame-2,imgExt);//need to change  
     pImg3=cvLoadImage(cur_fn,isColor);
   
     if (!pImg)    
     {
      std::cout<<"can't open an image file"<<std::endl;
     }
	Mat mtx(pImg);       // IplImage格式转换成Mat格式
    Mat mtx2(pImg2);     // IplImage格式转换成Mat格式
	Mat mtx3(pImg3);     // IplImage格式转换成Mat格式
    //为了方便使用后一帧减去前一帧:
	img_src3 = mtx;      //当前帧
	img_src2 = mtx2;     //第二帧
	img_src1 = mtx3;     //第一帧
	//img_src3;//3帧法需要3帧图片

    namedWindow("MyWindow", CV_WINDOW_AUTOSIZE);
    imshow("MyWindow", mtx);
	cout<<"运行到第 "<< frameCount<<" 帧 "<<endl;
    waitKey(1);

	cvtColor(img_src1,gray1,CV_BGR2GRAY);
    //imshow("第一帧video_src1",img_src1);//可以事先不用新建一个窗口
    //waitKey(5);
    cvtColor(img_src2,gray2,CV_BGR2GRAY);
    //imshow("第二帧video_src2",img_src2);//可以事先不用新建一个窗口
	//waitKey(5);
	cvtColor(img_src3,gray3,CV_BGR2GRAY);
    //imshow("第三帧即当前帧video_src3",img_src2);//可以事先不用新建一个窗口
    //waitKey(5);
    subtract(gray2,gray1,gray_diff1);//第二帧减第一帧
    subtract(gray3,gray2,gray_diff2);//第三帧减第二帧

   for(int i=0;i<gray_diff1.rows;i++)
        for(int j=0;j<gray_diff1.cols;j++)
        {
            if(abs(gray_diff1.at<unsigned char>(i,j))>=threshold_diff1)//这里模板参数一定要用unsigned char,否则就一直报错
                gray_diff1.at<unsigned char>(i,j)=255;            //第一次相减阈值处理
            else gray_diff1.at<unsigned char>(i,j)=0;

            if(abs(gray_diff2.at<unsigned char>(i,j))>=threshold_diff2)//第二次相减阈值处理
                gray_diff2.at<unsigned char>(i,j)=255;
            else gray_diff2.at<unsigned char>(i,j)=0;
        }
    bitwise_and(gray_diff1,gray_diff2,gray);
    imshow("运动目标foreground",gray);
	waitKey(5);
        

       Mat ero ;
    Mat dil ;
    Mat ero_dil ;
    Mat gaosi ;
    erode(gray,ero,cv::Mat());            //腐蚀
    dilate(gray,dil,cv::Mat());            //膨胀
    dilate(ero,ero_dil,cv::Mat());        //腐蚀后再膨胀
    imshow("腐蚀后的二值图片",ero);        //可以事先不用新建一个窗口  
    waitKey(5);    
    imshow("膨胀后的二值图片",dil);        //可以事先不用新建一个窗口  
    waitKey(5);  
    imshow("腐蚀后再膨胀后的二值图片",ero_dil);        //可以事先不用新建一个窗口  
    waitKey(5);  
    GaussianBlur(gray,gaosi,Size(5,5),0,0);            //高斯滤波
    imshow("高斯滤波后的二值图片",gaosi);        //可以事先不用新建一个窗口 
    waitKey(5);    

       startFrame++;
	frameCount++;
	frames++;
	}
    rename(videoName,fullVideoName);//移动文件到指定文件夹
	cout<<"起始帧为: "<<tmpFrame<<endl;
    cout<<"total frames 为: "<<frames<<"  have been write to video."<<endl;

    system("pause");

    return 0;
 }
//该函数借鉴了网上资料,自动创建多级目录
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;
}
 

参考文献:

1.http://blog.csdn.net/sway_2012/article/details/7786465

2.http://www.cnblogs.com/tornadomeet/archive/2012/05/01/2477629.html


  • 0
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值