Opencv--关于视频检测的项目

前段时间做了一个关于视频检测的小项目。目的是检测一段视频中灰色球员的运动和统计,之前学的图像处理都是线检测部分,这次涉及到视频过渡其实也没有想象中那么难。

这里还是采用opencv1.0来写的程序,以后要用Mat来写啦。贴上代码。效果不是太好。

#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std;
using namespace cv;

int main( int argc, char** argv )
{
	//uchar table[256]; 
  IplImage* pFrame = NULL;
  IplImage* pFrImg = NULL;
  IplImage* pBkImg = NULL;//背景RGB,选用120到175灰度级
  IplImage* pBkcanny = NULL;
   CvMemStorage *storage = cvCreateMemStorage(); 
  Mat pFrameMat ,pFrMat ,pBkMat; 

  CvCapture* pCapture = NULL;
  pCapture = cvCaptureFromFile("NBA.mp4"); //读取视频
  int nFrmNum = 0;
  
  //创建窗口 
  cvNamedWindow("video", 1);
  //使窗口有序排列
  cvMoveWindow("video", 30, 0);
 
  if( argc > 2 )
    {
      fprintf(stderr, "Usage: bkgrd [video_file_name]/n");
      return -1;
    }
  //打开视频文件
  if(argc == 2)
    if( !(pCapture = cvCaptureFromFile("NBA.mp4")))
      {
    fprintf(stderr, "Can not open video file %s/n", "NBA.mp4");
    return -2;
      }
     //逐帧读取视频
   cvSetCaptureProperty(pCapture, CV_CAP_PROP_POS_FRAMES, (double)1);  //定位到帧,经检测 只有帧定位较为精确
   while(pFrame = cvQueryFrame( pCapture ))   //抓取并返回帧,不能直接处理帧
    {
      nFrmNum++;
      //如果是第一帧,需要申请内存并初始化
	  //cout<<nFrmNum<<endl;
      if(nFrmNum == 1)
    {
      pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);  
      pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);
      pBkMat    = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);    //建立矩阵
      pFrMat    = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);
      pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1); 
      //cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);  //彩色图转换成灰度图像
      //cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);
    }
      else
    {   
	  cvSmooth(pFrame, pFrame, CV_GAUSSIAN, 3, 3); //高斯平滑
	  //transpose(pFrMat,pp);IplImage转Mat便于操作,但是会带来额外的地址操作,花了大量时间后还是弃用
 
      // 遍历筛选需要像素部分,对感兴趣区域操作
      //uchar * p = pFrMat.data;   //内置指针
	
      for (int i = 0; i <pFrame->height; i++)  
      {  
          for (int j = 0; j <pFrame->width; j++)  
	     {           
		  //间接访问,设置图片BGR
           CvScalar s=cvGet2D(pFrame,i,j); //其中i代表height;j代表width。    
           if(s.val[0]>190)   //去蓝色
		   {
			if((s.val[1]>60)&&(s.val[1]<170)&&(s.val[2]>60)&&(s.val[2]<170))
				s.val[0]=s.val[1]=s.val[2]=0;
			else
				s.val[0]=s.val[1]=s.val[2]=255;
		    }else{
			if(((s.val[2]<110)||(s.val[2]>130))&&((s.val[1]<110)||(s.val[1]>130)) )  //去红色
			  s.val[0]=s.val[1]=s.val[2]=0;
		    else
		     s.val[0]=s.val[1]=s.val[2]=255;//灰色球员进行提取
		    }
		  cvSet2D(pFrame,i,j,s);
          }  
      } 
	  //写一个边缘直线检测函数canny,去除边界以外的区域,可以滤波掉较小的部分(观众席)
     }	 
	  //双线程同时读写一个变量出问题?
	  //cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);  //处理灰度图像pFrImg就要用另一个形式。这里直接操作三通道
	  // 进行形态学滤波,去掉噪音 
      //cvErode(pFrame, pFrame, 0, 1);
      //cvDilate(pFrame, pFrame, 0, 1);
	  //canny检测,出现空间不足的错误?
	  //pBkcanny = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,3); 
	  //cvCanny(pFrImg,pBkImg,50,200,3);
	  //霍夫检测直线
	  //cvHoughLines2(pBkImg,storage,1,CV_PI/180,80,50,10);
	  //cvCvtColor(pBkImg, pBkcanny, CV_GRAY2BGR);//单通道转三通道
	  
	  cvSmooth(pFrame, pFrame, CV_GAUSSIAN, 5, 5); //高斯平滑
      cvShowImage("video",pFrame);
      //此等待也为cvShowImage函数提供时间完成显示
      if( cvWaitKey(2) >= 0 )
        break;
      } 
  //销毁窗口,释放图像和矩阵
  cvDestroyWindow("video");
  
  cvReleaseImage(&pFrImg);
  cvReleaseImage(&pBkImg);
  cvReleaseImage(&pFrame);
  cvReleaseImage(&pBkcanny);
  cvReleaseMemStorage(&storage);
  pFrameMat.release();
  pFrMat.release();
  pBkMat.release();
  cvReleaseCapture(&pCapture);
  return 0;
}
效果图:

Opencv--关于视频检测的项目_第1张图片

熟悉NBA的童鞋应该就可以很快识别图中的球员,但对于大部分童鞋来说可能还是有点问题,效果待改进。

你可能感兴趣的:(Opencv--关于视频检测的项目)