[opencv]目标追踪之前景建模(定期背景更新模型)

这篇博客主要参考了《opencv2计算机视觉编程手册》中的chap10中的10.6提取视频中的前景物体的定期更新背景模型。该书在实现这个模型时,编写了一个关于处理视频的类,进行了封装。而下面是我根据书的源代码稍作改写,方便以后写实验性质的代码进行参考:

#include
#include
#include
#include
using namespace std;
using namespace cv;
void process(Mat& frame,Mat &background,Mat &backImage,Mat &foreground,Mat &output,int threshold,double learningRate) {
	//当前灰度图像
	Mat gray;
	//将读取的帧图像转化为灰度图像
	cvtColor(frame, gray, CV_BGR2GRAY);
	if (background.empty())
		//第一帧  
		gray.convertTo(background, CV_32F);
	//背景转为CV_8U格式以便求取和当前帧差的绝对值  
	background.convertTo(backImage, CV_8U);
	//求当前帧与背景的差别  
	absdiff(backImage, gray, foreground);
	//过滤掉前景中与背景差别不大的扰动点  
	cv::threshold(foreground, output, threshold, 255, THRESH_BINARY_INV);
	//更新背景,output作为掩码  
	accumulateWeighted(gray, background, learningRate, output);
}

int main() {
	//视频路径
	string FilePath = "E:/study/book/opencv/opencv-2-cookbook-src-master/images/bike.avi";
	//读取视频
	VideoCapture capture(FilePath);
	if (!capture.isOpened()) {
		cout << "Can't open the video!" << endl;
		return  1;
	}
	//读取帧率
	double rate = capture.get(CV_CAP_PROP_FPS);
	bool stop(false);
	namedWindow("Extracted Frame");
	Mat frame;
	int delay = 1000 / rate;
	Mat gray;	//当前灰度图像
	Mat background;//累积的背景图像
	Mat backImage;	//背景图像
	Mat foreground;//前景图像
	Mat output;
	double learningRate = 0.01;
	int threshold = 10;
	while (!stop) {
		if (!capture.read(frame))
			break;
		//处理的程序应该放在这里...
		process(frame, background, backImage, foreground, output, threshold, learningRate);
		imshow("Extracted Frame", output);
		if (waitKey(delay) > 0)
			stop = true;
	
	}
	capture.release();
	waitKey();
	return 0;
}
整理这个代码主要想要学习以下几点:

1.学习这个框架,以后对视频进行处理时,只需要在“//处理的程序应该放在这里...”下面填写对每帧图像进行处理的程序即可

2.if (!capture.read(frame))
break;

很巧妙,这个语句将帧传入到frame中,且也用做控制循环是否退出

3.看看process函数是如何实现"定期背景更新模型"的[opencv]目标追踪之前景建模(定期背景更新模型)_第1张图片

主要是实现上面图片的那个公式

accumulateWeighted实现了滑动平均值的计算,其具体功能如下:

[opencv]目标追踪之前景建模(定期背景更新模型)_第2张图片

函数是浮点型运算,要转化类型

accumulateWeighted(gray, background, learningRate, output);也就是:

    background=(1-alpha)*background+alpha*gray

gray是由frame转化来到(当前帧图像)cvtColor(frame, gray, CV_BGR2GRAY);

background是累积的背景图像,刚开始认为是第一帧frame,然后利用

accumulateWeighted(gray, background, learningRate, output);

来计算累积值。

但程序中还有几行代码:

background.convertTo(backImage, CV_8U);
absdiff(backImage, gray, foreground);
cv::threshold(foreground, output, threshold, 255, THRESH_BINARY_INV);

分析其作用:

absdiff的用法:[opencv]目标追踪之前景建模(定期背景更新模型)_第3张图片

即foreground是前景,通过原frame减去背景得到,而cv::threshold的用法请参照:

http://blog.csdn.net/iracer/article/details/49232703

这里实现的功能如下:

output=0 if foreground>threshold;

  =255, otherwise

其实实现的是过滤掉与背景差距不大的扰动点。

你可能感兴趣的:(C++)