使用OpenCV实现运动背景的重建

 声明:本文转载 曾青松的专栏,为便于学习转帖至此,如有需要请查看原始出处。
  1. void CObjectDetectDlg::OnButtonOpenfile()    
  2.   
  3. {   
  4.   
  5.     // TODO: Add your control notification handler code here   
  6.   
  7.     // 文件打开对话框   
  8.   
  9.     CFileDialog dlg(true,"*.avi",NULL,NULL,"*.avi|*.avi||");   
  10.   
  11.     if (dlg.DoModal()==IDOK)   
  12.   
  13.     {   
  14.   
  15.         strAviFilePath = dlg.GetPathName();   
  16.   
  17.     }else  
  18.   
  19.     {   
  20.   
  21.         return;   
  22.   
  23.     }   
  24.   
  25.        
  26.   
  27. }   
  28.   
  29.   
  30.   
  31. void CObjectDetectDlg::OnButtonProcess()    
  32.   
  33. {   
  34.   
  35.     // TODO: Add your control notification handler code here   
  36.   
  37.     //声明IplImage指针   
  38.   
  39.     IplImage* pFrame = NULL;   
  40.   
  41.     IplImage* pFrImg = NULL;   
  42.   
  43.     IplImage* pBkImg = NULL;   
  44.   
  45.        
  46.   
  47.     CvMat* pFrameMat = NULL;   
  48.   
  49.     CvMat* pFrMat = NULL;   
  50.   
  51.     CvMat* pBkMat = NULL;   
  52.   
  53.        
  54.   
  55.     CvCapture* pCapture = NULL;   
  56.   
  57.        
  58.   
  59.     int nFrmNum = 0;   
  60.   
  61.        
  62.   
  63.     //打开AVI视频文件   
  64.   
  65.     if(strAviFilePath=="")  //判断文件路径是否为空   
  66.   
  67.     {   
  68.   
  69.         MessageBox("请先选择AVI视频文件!");   
  70.   
  71.         return;   
  72.   
  73.     }else  
  74.   
  75.     {   
  76.   
  77.         if(!(pCapture = cvCaptureFromFile(strAviFilePath)))   
  78.   
  79.         {   
  80.   
  81.             MessageBox("打开AVI视频文件失败!");   
  82.   
  83.             return;   
  84.   
  85.         }   
  86.   
  87.     }   
  88.   
  89.        
  90.   
  91.     //创建窗口   
  92.   
  93.     cvNamedWindow("Video", 1);   
  94.   
  95.     cvNamedWindow("Background",1);   
  96.   
  97.     cvNamedWindow("Foreground",1);   
  98.   
  99.        
  100.   
  101.     //使窗口有序排列,窗口宽330   
  102.   
  103.     cvMoveWindow("Video", 30, 0);   
  104.   
  105.     cvMoveWindow("Background", 360, 0);   
  106.   
  107.     cvMoveWindow("Foreground", 690, 0);   
  108.   
  109.        
  110.   
  111.     //逐帧读取视频   
  112.   
  113.     while(pFrame = cvQueryFrame( pCapture ))   
  114.   
  115.     {   
  116.   
  117.         nFrmNum++;   
  118.   
  119.            
  120.   
  121.         //如果是第一帧,需要申请内存,并初始化   
  122.   
  123.         if(nFrmNum == 1)   
  124.   
  125.         {   
  126.   
  127.             pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1); // 存放背景图像(灰度)   
  128.   
  129.             pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height), IPL_DEPTH_8U,1); // 存放中间图像(灰度)   
  130.   
  131.                
  132.   
  133.             pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);   
  134.   
  135.             pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);   
  136.   
  137.             pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);   
  138.   
  139.                
  140.   
  141.             //转化成单通道图像再处理(灰度)   
  142.   
  143.             cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);   
  144.   
  145.             cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);   
  146.   
  147.                
  148.   
  149.             cvConvert(pFrImg, pFrameMat);   
  150.   
  151.             cvConvert(pFrImg, pFrMat);   
  152.   
  153.             cvConvert(pFrImg, pBkMat);   
  154.   
  155.         }   
  156.   
  157.         else  
  158.   
  159.         {   
  160.   
  161.             cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY); //转化成单通道图像再处理(灰度)   
  162.   
  163.             cvConvert(pFrImg, pFrameMat);   
  164.   
  165.                
  166.   
  167.             //高斯滤波先,以平滑图像   
  168.   
  169.             //cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);   
  170.   
  171.                
  172.   
  173.             //当前帧跟背景图相减(求背景差并取绝对值)   
  174.   
  175.            cvAbsDiff(pFrameMat, pBkMat, pFrMat);   
  176.   
  177.                
  178.   
  179.             //二值化前景图(这里采用特定阈值进行二值化)   
  180.   
  181.             cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);   
  182.   
  183.                
  184.   
  185.             //进行形态学滤波,去掉噪音   
  186.   
  187.             cvErode(pFrImg, pFrImg, 0, 1);   
  188.   
  189.             cvDilate(pFrImg, pFrImg, 0, 1);   
  190.   
  191.                
  192.   
  193.             //滑动平均更新背景(求平均)   
  194.   
  195.             cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);   
  196.   
  197.             //将背景转化为图像格式,用以显示   
  198.   
  199.             cvConvert(pBkMat, pBkImg);   
  200.   
  201.                
  202.   
  203.             // 保持原图像的旋转方向   
  204.   
  205.             pBkImg->origin = pFrImg->origin = pFrame->origin;   
  206.   
  207.                
  208.   
  209.             //显示图像   
  210.   
  211.             // cvFlip(pFrame, pFrame, 0);   
  212.   
  213.             //cvFlip(pBkImg, pBkImg, 0); //转置一下,否则图像是颠倒的   
  214.   
  215.             cvFlip(pFrImg, pFrImg, 0);   
  216.   
  217.                
  218.   
  219.             //显示图像   
  220.   
  221.             cvShowImage("Video", pFrame);   
  222.   
  223.             cvShowImage("Background", pBkImg);   
  224.   
  225.             cvShowImage("Foreground", pFrImg);   
  226.   
  227.                
  228.   
  229.             //如果有按键事件,则跳出循环   
  230.   
  231.             //此等待也为cvShowImage函数提供时间完成显示   
  232.   
  233.             //等待时间可以根据CPU速度调整   
  234.   
  235.             if( cvWaitKey(2) >= 0 )   
  236.   
  237.                 break;   
  238.   
  239.         }   
  240.   
  241.     }   
  242.   
  243.        
  244.   
  245.     //销毁窗口   
  246.   
  247.     cvDestroyWindow("Video");   
  248.   
  249.     cvDestroyWindow("Background");   
  250.   
  251.     cvDestroyWindow("Foreground");   
  252.   
  253.        
  254.   
  255.     //释放图像和矩阵   
  256.   
  257.     cvReleaseImage(&pFrImg);   
  258.   
  259.     cvReleaseImage(&pBkImg);   
  260.   
  261.        
  262.   
  263.     cvReleaseMat(&pFrameMat);   
  264.   
  265.     cvReleaseMat(&pFrMat);   
  266.   
  267.     cvReleaseMat(&pBkMat);   
  268.   
  269.        
  270.   
  271.     cvReleaseCapture(&pCapture);   
  272.   
  273.        
  274.   
  275.        
  276.   
  277. }   
  278.   
  279.   
  280.   
  281.   
  282.   
  283. //运动目标检测,直接从摄像机获取图像   
  284.   
  285. void CObjectDetectDlg::OnButtonCamer()    
  286.   
  287. {   
  288.   
  289.        
  290.   
  291.     //声明IplImage指针   
  292.   
  293.     IplImage* pFrame = NULL;   
  294.   
  295.     IplImage* pFrImg = NULL;   
  296.   
  297.     IplImage* pBkImg = NULL;   
  298.   
  299.        
  300.   
  301.     CvMat* pFrameMat = NULL;   
  302.   
  303.     CvMat* pFrMat = NULL;   
  304.   
  305.     CvMat* pBkMat = NULL;   
  306.   
  307.        
  308.   
  309.     CvCapture* pCapture = NULL;   
  310.   
  311.        
  312.   
  313.     int nFrmNum = 0;   
  314.   
  315.        
  316.   
  317.     //创建窗口   
  318.   
  319.     cvNamedWindow("video", 1);   
  320.   
  321.     cvNamedWindow("background",1);   
  322.   
  323.     cvNamedWindow("foreground",1);   
  324.   
  325.     //使窗口有序排列   
  326.   
  327.     cvMoveWindow("video", 30, 0);   
  328.   
  329.     cvMoveWindow("background", 360, 0);   
  330.   
  331.     cvMoveWindow("foreground", 690, 0);   
  332.   
  333.     //if( argc > 2 )   
  334.   
  335.     //{   
  336.   
  337.     // fprintf(stderr, "Usage: bkgrd [video_file_name]/n");   
  338.   
  339.     // return -1;   
  340.   
  341.     //}   
  342.   
  343.        
  344.   
  345.     ////打开摄像头   
  346.   
  347.     //if (argc ==1)   
  348.   
  349.     // if( !(pCapture = cvCaptureFromCAM(-1)))   
  350.   
  351.     // {   
  352.   
  353.     //  fprintf(stderr, "Can not open camera./n");   
  354.   
  355.     //  return -2;   
  356.   
  357.     // }   
  358.   
  359.        
  360.   
  361.     //打开视频文件   
  362.   
  363.     //if(argc == 2)   
  364.   
  365.     //if( !(pCapture = cvCaptureFromFile(argv[1])))   
  366.   
  367.     //if( !(pCapture = cvCaptureFromFile(this->strAviFilePath)))   
  368.   
  369.     if( !(pCapture = cvCaptureFromCAM(-1)))    
  370.   
  371.     {   
  372.   
  373.            MessageBox("打开摄像机视频失败!");   
  374.   
  375.             return;   
  376.   
  377.         //fprintf(stderr, "Can not open video file %s/n", this->strAviFilePath);   
  378.   
  379.         //  return -2;   
  380.   
  381.     }   
  382.   
  383.        
  384.   
  385.     //逐帧读取视频   
  386.   
  387.     while(pFrame = cvQueryFrame( pCapture ))   
  388.   
  389.     {   
  390.   
  391.         nFrmNum++;   
  392.   
  393.            
  394.   
  395.         //如果是第一帧,需要申请内存,并初始化   
  396.   
  397.         if(nFrmNum == 1)   
  398.   
  399.         {   
  400.   
  401.             pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);   
  402.   
  403.             pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);   
  404.   
  405.                
  406.   
  407.             pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);   
  408.   
  409.             pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);   
  410.   
  411.             pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);   
  412.   
  413.                
  414.   
  415.             //转化成单通道图像再处理   
  416.   
  417.             cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);   
  418.   
  419.             cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);   
  420.   
  421.                
  422.   
  423.             cvConvert(pFrImg, pFrameMat);   
  424.   
  425.             cvConvert(pFrImg, pFrMat);   
  426.   
  427.             cvConvert(pFrImg, pBkMat);   
  428.   
  429.         }   
  430.   
  431.         else  
  432.   
  433.         {   
  434.   
  435.             cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);   
  436.   
  437.             cvConvert(pFrImg, pFrameMat);   
  438.   
  439.             //高斯滤波先,以平滑图像   
  440.   
  441.             //cvSmooth(pFrameMat, pFrameMat, CV_GAUSSIAN, 3, 0, 0);   
  442.   
  443.                
  444.   
  445.             //当前帧跟背景图相减   
  446.   
  447.             <FONT style="BACKGROUND-COLOR: #00ffff">cvAbsDiff</FONT>(pFrameMat, pBkMat, pFrMat);   
  448.   
  449.                
  450.   
  451.             //二值化前景图   
  452.   
  453.             cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);   
  454.   
  455.                
  456.   
  457.             //进行形态学滤波,去掉噪音    
  458.   
  459.             //cvErode(pFrImg, pFrImg, 0, 1);   
  460.   
  461.             //cvDilate(pFrImg, pFrImg, 0, 1);   
  462.   
  463.                
  464.   
  465.             //更新背景   
  466.   
  467.             cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);   
  468.   
  469.             //将背景转化为图像格式,用以显示   
  470.   
  471.             cvConvert(pBkMat, pBkImg);   
  472.   
  473.                
  474.   
  475.             // 保持原图像的旋转方向   
  476.   
  477.             pBkImg->origin = pFrImg->origin = pFrame->origin;   
  478.   
  479.                
  480.   
  481.             //显示图像   
  482.   
  483.             // cvFlip(pFrame, pFrame, 0);   
  484.   
  485.             //cvFlip(pBkImg, pBkImg, 0); //转置一下,否则图像是颠倒的   
  486.   
  487.             //cvFlip(pFrImg, pFrImg, 0);   
  488.   
  489.                
  490.   
  491.             cvShowImage("video", pFrame);   
  492.   
  493.             cvShowImage("background", pBkImg);   
  494.   
  495.             cvShowImage("foreground", pFrImg);   
  496.   
  497.                
  498.   
  499.             //如果有按键事件,则跳出循环   
  500.   
  501.             //此等待也为cvShowImage函数提供时间完成显示   
  502.   
  503.             //等待时间可以根据CPU速度调整   
  504.   
  505.             if( cvWaitKey(2) >= 0 )   
  506.   
  507.                 break;   
  508.   
  509.         }   
  510.   
  511.            
  512.   
  513.     }   
  514.   
  515.        
  516.   
  517.     //销毁窗口   
  518.   
  519.     cvDestroyWindow("video");   
  520.   
  521.     cvDestroyWindow("background");   
  522.   
  523.     cvDestroyWindow("foreground");   
  524.   
  525.        
  526.   
  527.     //释放图像和矩阵   
  528.   
  529.     cvReleaseImage(&pFrImg);   
  530.   
  531.     cvReleaseImage(&pBkImg);   
  532.   
  533.        
  534.   
  535.     cvReleaseMat(&pFrameMat);   
  536.   
  537.     cvReleaseMat(&pFrMat);   
  538.   
  539.     cvReleaseMat(&pBkMat);   
  540.   
  541.        
  542.   
  543.     cvReleaseCapture(&pCapture);   
  544.   
  545. }  

你可能感兴趣的:(使用OpenCV实现运动背景的重建)