单高斯背景建模opencv仿真

本文介绍了如何利用高斯分布进行背景建模,每个像素点颜色值被视为服从高斯分布的随机过程。算法包括初始化背景模型、检测前景与背景像素,并给出背景值的更新公式。通过示例图片展示前景、背景和原图效果,特别指出opencv使用的是1.0版本。
摘要由CSDN通过智能技术生成

       高斯分布与背景建模的关系图像中每一个像素点的颜色值作为一个随机过程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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值