在本篇中,我们分别使用opencv提供的方法:BackgroundSubtractorMOG 和 CvBGCodeBookModel两种方式来实现video的运动跟踪。
在这里,首先要感谢: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; } } }
具体的代码讲解,请看之前提到的那个博客上有详细的描述。 具体效果如下:
这个是实例是有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);
最后对应的效果演示如下: 原始图像
背景减去之后图像
连通域分割后图像
原文:http://blog.csdn.net/u011630458/article/details/45875173