opencv实现运动追踪

简介

  在本篇中,我们分别使用opencv提供的方法:BackgroundSubtractorMOG 和 CvBGCodeBookModel两种方式来实现video的运动跟踪。

BackgroundSubtractorMOG

  在这里,首先要感谢:http://blog.csdn.net/yang_xian521/article/details/6991002 这篇blog的博主,非常感谢该博主,这里使用的实例来源于它。

具体代码

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/video.hpp>
 
#include <iostream>
 
using namespace cv;
using namespace std;
 
int main(int argc, char **argv){
	Mat frame; 
	Mat foreground;	// 前景图片
	VideoCapture capture(argv[1]);
 
	if (!capture.isOpened())
	{
		return 0;
	}
 
	namedWindow("Extracted Foreground");
	namedWindow("Source Video");
	// 混合高斯物体
	BackgroundSubtractorMOG mog;
	bool stop(false);
	while (!stop)
	{
		if (!capture.read(frame))
		{
			break;
		}
		// 更新背景图片并且输出前景
		mog(frame, foreground, 0.01);
		// 输出的前景图片并不是2值图片,要处理一下显示  
		threshold(foreground, foreground, 128, 255, THRESH_BINARY_INV);
		// show foreground
		imshow("Extracted Foreground", foreground);
		imshow("Source Video", frame);
		if (waitKey(10) == 27)
		{
			stop = true;
		}
	}
}

效果演示

  具体的代码讲解,请看之前提到的那个博客上有详细的描述。
具体效果如下:
                

CvBGCodeBookModel

  这个是实例是有opencv官方提供的实例bgfg_codebook.cpp简化而来。

具体代码

#include "opencv2/core/core.hpp"
#include "opencv2/video/background_segm.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/legacy/legacy.hpp"
 
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
 
using namespace std;
using namespace cv;
 
CvBGCodeBookModel* model = 0;
const int NCHANNELS = 3;
bool ch[NCHANNELS]={true,true,true}; // This sets what channels should be adjusted for background bounds
 
int main(int argc, const char** argv){
 
    int nframesToLearnBG = <a href="http://www.opengroup.org/onlinepubs/%3Cspan%20class=" nu19"="" style="text-decoration: none; color: rgb(11, 0, 128); background-image: none; background-position: initial initial; background-repeat: initial initial;">009695399/functions/atoi.html">atoi(argv[1]);
    string filename = argv[2];
    IplImage* rawImage = 0, *yuvImage = 0; //yuvImage is for codebook method
    IplImage *ImaskCodeBook = 0,*ImaskCodeBookCC = 0;
    CvCapture* capture = 0;
 
    int c, n, nframes = 0;
 
    model = cvCreateBGCodeBookModel(); //codebook方法中,初始化
 
    //Set color thresholds to default values
    model->modMin[0] = 3;
    model->modMin[1] = model->modMin[2] = 3;
    model->modMax[0] = 10;
    model->modMax[1] = model->modMax[2] = 10;
    model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10;
 
    bool pause = false;
    bool singlestep = false;
 
    capture = cvCreateFileCapture( filename.c_str() );
    if( !capture ){
        return -1;
    }
 
    //MAIN PROCESSING LOOP:
    for(;;){
        if(!pause){
            rawImage = cvQueryFrame(capture);
            ++nframes;
            if(!rawImage)
                break;
        }
        if(singlestep)
            pause = true;
 
        //First time:
        if(nframes == 1 && rawImage){
            yuvImage = cvCloneImage(rawImage);
            ImaskCodeBook = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
            ImaskCodeBookCC = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
            cvSet(ImaskCodeBook,cvScalar(255));
 
            cvNamedWindow( "Raw", 1 );
            cvNamedWindow( "ForegroundCodeBook",1);
            cvNamedWindow( "CodeBook_ConnectComp",1);
        }
 
        if(rawImage){
            cvCvtColor(rawImage, yuvImage, CV_BGR2YCrCb);//YUV For codebook method
            if(!pause && nframes-1 < nframesToLearnBG)
                cvBGCodeBookUpdate( model, yuvImage ); //codebook方法中,更新背景模型
 
            if(nframes-1 == nframesToLearnBG)
                cvBGCodeBookClearStale( model, model->t/2 ); //清除消极的codebook
 
            if( nframes-1 >= nframesToLearnBG){
                // Find foreground by codebook method
                cvBGCodeBookDiff(model, yuvImage, ImaskCodeBook);//codebook方法中,背景减除
                // This part just to visualize bounding boxes and centers if desired
                cvCopy(ImaskCodeBook,ImaskCodeBookCC);
                cvSegmentFGMask(ImaskCodeBookCC);
            }
            //Display
            cvShowImage("Raw", rawImage);
            cvShowImage("ForegroundCodeBook",ImaskCodeBook);
            cvShowImage("CodeBook_ConnectComp",ImaskCodeBookCC);
        }
 
        // User input:
        c = cvWaitKey(100)&0xFF;
    }
 
    cvReleaseCapture( &capture );
    cvDestroyWindow( "Raw" );
    cvDestroyWindow( "ForegroundCodeBook");
    cvDestroyWindow( "CodeBook_ConnectComp");
    return 0;
}

代码讲解

  1、运行时候需要传入两个参数:(1)背景计算的帧数. (2)使用的video文件。
    int nframesToLearnBG = <a href="http://www.opengroup.org/onlinepubs/%3Cspan%20class=" nu19"="" style="text-decoration: none; color: rgb(11, 0, 128); background-image: none; background-position: initial initial; background-repeat: initial initial;">009695399/functions/atoi.html">atoi(argv[1]);
    string filename = argv[2];
  2、初始化codebook,设置它计算使用的的相关阀值。
    CvBGCodeBookModel* model = 0;
 
    model = cvCreateBGCodeBookModel(); //codebook方法中,初始化
 
    //Set color thresholds to default values
    model->modMin[0] = 3;
    model->modMin[1] = model->modMin[2] = 3;
    model->modMax[0] = 10;
    model->modMax[1] = model->modMax[2] = 10;
    model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10;
  3、打开传入的video文件。
    capture = cvCreateFileCapture( filename.c_str() );
    if( !capture ){
        <a href="http://www.opengroup.org/onlinepubs/%3Cspan%20class=" nu19"="" style="text-decoration: none; color: rgb(11, 0, 128); background-image: none; background-position: initial initial; background-repeat: initial initial;">009695399/functions/printf.html">printf( "Can not initialize video capturing\n\n" );
        return -1;
    }
  4、在for的死循环中,不断的从video文件中去出一帧数据。
    rawImage = cvQueryFrame(capture);
    ++nframes;
    if(!rawImage)
        break;
  5、如果是处理第一帧数据,初始化之后会使用的图像:yuvImage ImaskCodeBook ImaskCodeBookCC和创建相关的显示窗口。
if(nframes == 1 && rawImage){
    yuvImage = cvCloneImage(rawImage);
    ImaskCodeBook = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
    ImaskCodeBookCC = cvCreateImage(cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
    cvSet(ImaskCodeBook,cvScalar(255));
 
    cvNamedWindow( "Raw", 1 );
    cvNamedWindow( "ForegroundCodeBook",1);
    cvNamedWindow( "CodeBook_ConnectComp",1);
}
  6、首先将处理图像转换成yuv,然后如果当前处理的帧数小于之前传入的背景计算帧数,则使用cvBGCodeBookUpdate进行背景模型跟踪。如果当前帧数等于之前传入的背景
计算帧数,则使用cvBGCodeBookClearStale清除消极的codebook,到了这一步就相当于背景部分训练计算完成。
     cvCvtColor(rawImage, yuvImage, CV_BGR2YCrCb);//YUV For codebook method
     if(!pause && nframes-1 < nframesToLearnBG)
          cvBGCodeBookUpdate( model, yuvImage ); //codebook方法中,更新背景模型
 
     if(nframes-1 == nframesToLearnBG)
          cvBGCodeBookClearStale( model, model->t/2 ); //清除消极的codebook
  7、使用cvBGCodeBookDiff来进行背景减除,获得运动部分的图像,保存在ImaskCodeBook中。接着使用cvSegmentFGMask做连通域分割,从而获得更好的运动图像,保存在
ImaskCodeBookCC中。
     if( nframes-1 >= nframesToLearnBG){
          // Find foreground by codebook method
          cvBGCodeBookDiff(model, yuvImage, ImaskCodeBook);//codebook方法中,背景减除
          // This part just to visualize bounding boxes and centers if desired
          cvCopy(ImaskCodeBook,ImaskCodeBookCC);
          cvSegmentFGMask(ImaskCodeBookCC);
      }
  8、最后将原始图像(rawImage)、背景减去之后图像(ImaskCodeBook)和连通域分割后图像(ImaskCodeBookCC)分别显示出来。
     //Display
     cvShowImage("Raw", rawImage);
     cvShowImage("ForegroundCodeBook",ImaskCodeBook);
     cvShowImage("CodeBook_ConnectComp",ImaskCodeBookCC);

效果演示

  最后对应的效果演示如下:
                                    原始图像                                                                   
                       opencv实现运动追踪_第1张图片   
                                  背景减去之后图像
                       opencv实现运动追踪_第2张图片    
                                 连通域分割后图像
                       
                            

你可能感兴趣的:(opencv,图像处理)