您的位置:首页 > 运维架构

单高斯背景建模opencv仿真

2014-09-13 20:03 316 查看
高斯分布与背景建模的关系:图像中每一个像素点的颜色值作为一个随机过程X,并假设该点的像素值出现的概率服从高斯分布。令I(x,y,t)表示像素点(x,y,t)在t时刻的像素值,则有:



其中



分别为t时刻该像素高斯分布的期望值和标准差。

算法流程:

1.用第一帧图像数据初始化背景模型,其中std_init通常设置为20。







2.检测前景与背景像素。

背景像素检测公式:


前景像素检测公式:


3.对





背景值进行更新,更新公式如下:







4.返回到2直至停止。

#include <stdlib.h>
#include <stdio.h>
#include <highgui.h>
#include <cv.h>
#include <math.h>
#include <cxcore.h>

int main(int argc,char *argv[])
{
	//新建窗口
	cvNamedWindow("origin",CV_WINDOW_AUTOSIZE);
	cvNamedWindow("background",CV_WINDOW_AUTOSIZE);
	cvNamedWindow("foreground",CV_WINDOW_AUTOSIZE);
	cvMoveWindow("origin", 1100, 400);
	cvMoveWindow("background", 600, 400);
	cvMoveWindow("foreground", 100, 400);

	double alpha = 0.5;//背景建模alpha值
	double std_int = 20;//初始化标准差
	double var_int = std_int*std_int;//初始化方差
	double lamda = 2.5*1.2;//背景更新参数

	//视频文件
	CvCapture *capture = NULL;
	//读取视频文件
	if(argc==1)
	{
		//从摄像头读入
		capture = cvCreateCameraCapture(0);
	}
	else if(argc==2)
	{
		//从文件读入
		capture = cvCreateFileCapture(argv[1]);
	}
	else
	{
		//读入错误
		printf("input error\n");
		return -1;
	}

	IplImage *frame = NULL;//原始图像
	IplImage *frame_u=NULL;//期望图像(背景)
	IplImage *frame_d=NULL;//前景图像
	IplImage *frame_var=NULL;//方差图像
	IplImage *frame_std=NULL;//标准差

	CvScalar pixel={0};//像素原始值
	CvScalar pixel_u={0};//像素期望值
	CvScalar pixel_d={0};//像素前景
	CvScalar pixel_var={0};//像素方差
	CvScalar pixel_std={0};//像素标准差

	//初始化frame_u,frame_d,frame_var,frame_std
	frame=cvQueryFrame(capture);
	frame_u=cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,3);
	frame_d=cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,3);
	frame_var=cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,3);
	frame_std=cvCreateImage(cvSize(frame->width,frame->height),IPL_DEPTH_8U,3);

	for(int y=0;y<frame->height;++y)
	{
		for(int x=0;x<frame->width;++x)
		{
			pixel = cvGet2D(frame,y,x);

			pixel_u.val[0]=pixel.val[0];
			pixel_u.val[1]=pixel.val[1];
			pixel_u.val[2]=pixel.val[2];

			pixel_d.val[0]=0;
			pixel_d.val[1]=0;
			pixel_d.val[2]=0;

			pixel_std.val[0]=std_int;
			pixel_std.val[1]=std_int;
			pixel_std.val[2]=std_int;

			pixel_var.val[0]=var_int;
			pixel_var.val[1]=var_int;
			pixel_var.val[2]=var_int;

			cvSet2D(frame_u,y,x,pixel_u);
			cvSet2D(frame_d,y,x,pixel_d);
			cvSet2D(frame_var,y,x,pixel_var);
			cvSet2D(frame_std,y,x,pixel_std);
		}
	}

	while(cvWaitKey(33)!=27)//按ESC键退出,帧率33ms
	{
		frame = cvQueryFrame(capture);
		//视频结束退出
		if(!frame)
		{
			break;
		}
		//单高斯背景更新
		for(int y=0;y<frame->height;++y)
		{
			for(int x=0;x<frame->width;++x)
			{
				pixel=cvGet2D(frame,y,x);
				pixel_u=cvGet2D(frame_u,y,x);
				pixel_d=cvGet2D(frame_d,y,x);
				pixel_std=cvGet2D(frame_std,y,x);
				pixel_var=cvGet2D(frame_var,y,x);

				//|I-u|<lamda*std时认为是背景,进行更新
				if(fabs(pixel.val[0]-pixel_u.val[0])<lamda*pixel_std.val[0]&&
				   fabs(pixel.val[1]-pixel_u.val[1])<lamda*pixel_std.val[1]&&
				   fabs(pixel.val[2]-pixel_u.val[2])<lamda*pixel_std.val[2])
				{
					//更新期望u=(1-alpha)*u+alpha*I
					pixel_u.val[0]=(1-alpha)*pixel_u.val[0]+alpha*pixel.val[0];
				    pixel_u.val[1]=(1-alpha)*pixel_u.val[1]+alpha*pixel.val[1];
					pixel_u.val[2]=(1-alpha)*pixel_u.val[2]+alpha*pixel.val[2];

					//更新方差var=(1-alpha)*var+alpha*(I-u)^2
					pixel_var.val[0]=(1-alpha)*pixel_var.val[0]+
						alpha*(pixel.val[0]-pixel_u.val[0])*(pixel.val[0]-pixel_u.val[0]);
					pixel_var.val[1]=(1-alpha)*pixel_var.val[1]+
						alpha*(pixel.val[1]-pixel_u.val[1])*(pixel.val[1]-pixel_u.val[1]);
					pixel_var.val[2]=(1-alpha)*pixel_var.val[2]+
						alpha*(pixel.val[2]-pixel_u.val[2])*(pixel.val[2]-pixel_u.val[2]);
					//更新标准差
					pixel_std.val[0]=sqrt(pixel_var.val[0]);
					pixel_std.val[1]=sqrt(pixel_var.val[1]);
					pixel_std.val[2]=sqrt(pixel_var.val[2]);

					//写入矩阵
					cvSet2D(frame_u,y,x,pixel_u);
					cvSet2D(frame_var,y,x,pixel_var);
					cvSet2D(frame_std,y,x,pixel_std);
				}
				else
				{
					pixel_d.val[0]=pixel.val[0]-pixel_u.val[0];
					pixel_d.val[1]=pixel.val[1]-pixel_u.val[1];
					pixel_d.val[2]=pixel.val[2]-pixel_u.val[2];
					cvSet2D(frame_d,y,x,pixel_d);
				}
			}
		}
		//显示结果
		frame_u->origin=1;
		frame_u->origin=1;
		cvShowImage("origin",frame);
		cvShowImage("background",frame_u);
		cvShowImage("foreground",frame_d);
	}
	//释放内存
	cvReleaseCapture(&capture);
	cvReleaseImage(&frame);
	cvReleaseImage(&frame_u);
	cvReleaseImage(&frame_var);
	cvReleaseImage(&frame_std);
	cvDestroyWindow("origin");
	cvDestroyWindow("background");
	cvDestroyWindow("foreground");

	return 0;

}



从左到右,图片一次为前景,背景,原图。

备注:opencv使用的是1.0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: