单高斯背景建模
2015-06-10 19:48
267 查看
这些原理和算法流程,转自别人的博客,代码是自己实现的。
高斯分布与背景建模的关系:图像中每一个像素点的颜色值作为一个随机过程X,并假设该点的像素值出现的概率服从高斯分布。令I(x,y,t)表示像素点(x,y,t)在t时刻的像素值,则有:
其中
和
分别为t时刻该像素高斯分布的期望值和标准差。
算法流程:
1.用第一帧图像数据初始化背景模型,其中std_init通常设置为20。
2.检测前景与背景像素。
背景像素检测公式:
前景像素检测公式:
3.对
、
、
背景值进行更新,更新公式如下:
4.返回到2直至停止。
下面是详细的实现代码:
//单高斯背景建模
/*
#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);
double alpha = 0.05; //背景建模alpha值
double std_init = 20; //初始标准差
double var_init = std_init * std_init; //初始方差
double lamda = 2.5 * 1.2; //背景更新参数
//视频文件
CvCapture *capture = NULL;
//从文件读入
// capture = cvCreateFileCapture("E:\\新建文件夹\\cs.AVI");
capture = cvCreateFileCapture("D:\\VideoData\\SDC11945.AVI");
IplImage *frame = NULL; //原始图像
IplImage *frame_u = NULL; //期望图像
IplImage *frame_d = NULL; //前景图像
IplImage *frame_var = NULL; //方差图像
IplImage *frame_std = NULL; //标准差
//初始化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 j = 0; j < frame->height; ++j)
{
for (int i= 0; i< frame->width; ++i)
{
frame_u->imageData[j *frame->widthStep + i * 3 + 0] = (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0];
frame_u->imageData[j *frame->widthStep + i * 3 + 1] = (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 1];
frame_u->imageData[j *frame->widthStep + i * 3 + 2] = (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 2];
frame_d->imageData[j *frame->widthStep + i * 3 + 0] = 0;
frame_d->imageData[j *frame->widthStep + i * 3 + 1] =0;
frame_d->imageData[j *frame->widthStep + i * 3 + 2] = 0;
frame_var->imageData[j *frame->widthStep + i * 3 + 0] = var_init;
frame_var->imageData[j *frame->widthStep + i * 3 + 1] = var_init;
frame_var->imageData[j *frame->widthStep + i * 3 + 2] = var_init;
frame_std->imageData[j *frame->widthStep + i * 3 + 0] = std_init;
frame_std->imageData[j *frame->widthStep + i * 3 + 1] = std_init;
frame_std->imageData[j *frame->widthStep + i * 3 + 2] = std_init;
}
}
while (cvWaitKey(33) != 27) //按ESC键退出, 帧率33ms
{
frame = cvQueryFrame(capture);
//视频结束退出
if (!frame)
{
break;
}
//单高斯背景更新
for (int j= 0; j < frame->height; ++j)
{
for (int i = 0; i < frame->width; ++i)
{
//|I-u| < lamda*std 时认为是背景, 进行更新
if (abs( (unsigned char)frame->imageData[j *frame->widthStep + i * 3 + 0] - (unsigned char) frame_u->imageData[j *frame->widthStep + i * 3 + 0]) < lamda * std_init &&
abs( (unsigned char)frame->imageData[j *frame->widthStep + i * 3 + 1] - (unsigned char) frame_u->imageData[j *frame->widthStep + i * 3 + 1]) < lamda * std_init &&
abs( (unsigned char)frame->imageData[j *frame->widthStep + i * 3 + 2] -(unsigned char) frame_u->imageData[j *frame->widthStep + i * 3 + 2])< lamda * std_init)
{
//更新期望 u = (1-alpha)*u + alpha*I
frame_u->imageData[j *frame->widthStep + i * 3 + 0]= (1 - alpha) * (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0] + alpha *(unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0];
frame_u->imageData[j *frame->widthStep + i * 3 + 1]= (1 - alpha) * (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1] + alpha *(unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 1];
frame_u->imageData[j *frame->widthStep + i * 3 + 2]= (1 - alpha) *(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2]+ alpha *(unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 2];
//更新方差 var = (1-alpha)*var + alpha*(I-u)^2
frame_var->imageData[j *frame->widthStep + i * 3 + 0] =(1 - alpha) *( (unsigned char)frame_var->imageData[j *frame->widthStep + i * 3 + 0])+
alpha*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0] )
*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0] );
frame_var->imageData[j *frame->widthStep + i * 3 + 1] =(1 - alpha) *( (unsigned char)frame_var->imageData[j *frame->widthStep + i * 3 + 1])+
alpha*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1] )
*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1] );
frame_var->imageData[j *frame->widthStep + i * 3 + 2] =(1 - alpha) *( (unsigned char)frame_var->imageData[j *frame->widthStep + i * 3 + 2])+
alpha*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2] )
*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2] );
//更新标准差
frame_std->imageData[j *frame->widthStep + i * 3 + 0]=sqrt( frame_var->imageData[j *frame->widthStep + i * 3 + 0]*1.0);
frame_std->imageData[j *frame->widthStep + i * 3 + 1]=sqrt(frame_var->imageData[j *frame->widthStep + i * 3 + 1]*1.0);
frame_std->imageData[j *frame->widthStep + i * 3 + 2]=sqrt(frame_var->imageData[j *frame->widthStep + i * 3 + 2]*1.0);
}
else
{
frame_d->imageData[j *frame->widthStep + i * 3 + 0]= (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]- (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0];
frame_d->imageData[j *frame->widthStep + i * 3 + 1]= (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 1]- (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1];
frame_d->imageData[j *frame->widthStep + i * 3 + 2]= (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 2]- (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2];
}
}
}
//显示结果
frame_u->origin = 0;
frame_d->origin = 0;
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;
}
*/
高斯分布与背景建模的关系:图像中每一个像素点的颜色值作为一个随机过程X,并假设该点的像素值出现的概率服从高斯分布。令I(x,y,t)表示像素点(x,y,t)在t时刻的像素值,则有:
其中
和
分别为t时刻该像素高斯分布的期望值和标准差。
算法流程:
1.用第一帧图像数据初始化背景模型,其中std_init通常设置为20。
2.检测前景与背景像素。
背景像素检测公式:
前景像素检测公式:
3.对
、
、
背景值进行更新,更新公式如下:
4.返回到2直至停止。
下面是详细的实现代码:
//单高斯背景建模
/*
#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);
double alpha = 0.05; //背景建模alpha值
double std_init = 20; //初始标准差
double var_init = std_init * std_init; //初始方差
double lamda = 2.5 * 1.2; //背景更新参数
//视频文件
CvCapture *capture = NULL;
//从文件读入
// capture = cvCreateFileCapture("E:\\新建文件夹\\cs.AVI");
capture = cvCreateFileCapture("D:\\VideoData\\SDC11945.AVI");
IplImage *frame = NULL; //原始图像
IplImage *frame_u = NULL; //期望图像
IplImage *frame_d = NULL; //前景图像
IplImage *frame_var = NULL; //方差图像
IplImage *frame_std = NULL; //标准差
//初始化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 j = 0; j < frame->height; ++j)
{
for (int i= 0; i< frame->width; ++i)
{
frame_u->imageData[j *frame->widthStep + i * 3 + 0] = (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0];
frame_u->imageData[j *frame->widthStep + i * 3 + 1] = (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 1];
frame_u->imageData[j *frame->widthStep + i * 3 + 2] = (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 2];
frame_d->imageData[j *frame->widthStep + i * 3 + 0] = 0;
frame_d->imageData[j *frame->widthStep + i * 3 + 1] =0;
frame_d->imageData[j *frame->widthStep + i * 3 + 2] = 0;
frame_var->imageData[j *frame->widthStep + i * 3 + 0] = var_init;
frame_var->imageData[j *frame->widthStep + i * 3 + 1] = var_init;
frame_var->imageData[j *frame->widthStep + i * 3 + 2] = var_init;
frame_std->imageData[j *frame->widthStep + i * 3 + 0] = std_init;
frame_std->imageData[j *frame->widthStep + i * 3 + 1] = std_init;
frame_std->imageData[j *frame->widthStep + i * 3 + 2] = std_init;
}
}
while (cvWaitKey(33) != 27) //按ESC键退出, 帧率33ms
{
frame = cvQueryFrame(capture);
//视频结束退出
if (!frame)
{
break;
}
//单高斯背景更新
for (int j= 0; j < frame->height; ++j)
{
for (int i = 0; i < frame->width; ++i)
{
//|I-u| < lamda*std 时认为是背景, 进行更新
if (abs( (unsigned char)frame->imageData[j *frame->widthStep + i * 3 + 0] - (unsigned char) frame_u->imageData[j *frame->widthStep + i * 3 + 0]) < lamda * std_init &&
abs( (unsigned char)frame->imageData[j *frame->widthStep + i * 3 + 1] - (unsigned char) frame_u->imageData[j *frame->widthStep + i * 3 + 1]) < lamda * std_init &&
abs( (unsigned char)frame->imageData[j *frame->widthStep + i * 3 + 2] -(unsigned char) frame_u->imageData[j *frame->widthStep + i * 3 + 2])< lamda * std_init)
{
//更新期望 u = (1-alpha)*u + alpha*I
frame_u->imageData[j *frame->widthStep + i * 3 + 0]= (1 - alpha) * (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0] + alpha *(unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0];
frame_u->imageData[j *frame->widthStep + i * 3 + 1]= (1 - alpha) * (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1] + alpha *(unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 1];
frame_u->imageData[j *frame->widthStep + i * 3 + 2]= (1 - alpha) *(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2]+ alpha *(unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 2];
//更新方差 var = (1-alpha)*var + alpha*(I-u)^2
frame_var->imageData[j *frame->widthStep + i * 3 + 0] =(1 - alpha) *( (unsigned char)frame_var->imageData[j *frame->widthStep + i * 3 + 0])+
alpha*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0] )
*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0] );
frame_var->imageData[j *frame->widthStep + i * 3 + 1] =(1 - alpha) *( (unsigned char)frame_var->imageData[j *frame->widthStep + i * 3 + 1])+
alpha*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1] )
*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1] );
frame_var->imageData[j *frame->widthStep + i * 3 + 2] =(1 - alpha) *( (unsigned char)frame_var->imageData[j *frame->widthStep + i * 3 + 2])+
alpha*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2] )
*((unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]-(unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2] );
//更新标准差
frame_std->imageData[j *frame->widthStep + i * 3 + 0]=sqrt( frame_var->imageData[j *frame->widthStep + i * 3 + 0]*1.0);
frame_std->imageData[j *frame->widthStep + i * 3 + 1]=sqrt(frame_var->imageData[j *frame->widthStep + i * 3 + 1]*1.0);
frame_std->imageData[j *frame->widthStep + i * 3 + 2]=sqrt(frame_var->imageData[j *frame->widthStep + i * 3 + 2]*1.0);
}
else
{
frame_d->imageData[j *frame->widthStep + i * 3 + 0]= (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 0]- (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 0];
frame_d->imageData[j *frame->widthStep + i * 3 + 1]= (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 1]- (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 1];
frame_d->imageData[j *frame->widthStep + i * 3 + 2]= (unsigned char) frame->imageData[j *frame->widthStep + i * 3 + 2]- (unsigned char)frame_u->imageData[j *frame->widthStep + i * 3 + 2];
}
}
}
//显示结果
frame_u->origin = 0;
frame_d->origin = 0;
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;
}
*/
相关文章推荐
- codeforces 549C
- P269 2
- 各种在线手册
- Android的selector,背景选择器 以及.9.png
- HOG特征—简介
- Laravel查看当前已有的路由信息
- Mac环境下反编译apk
- md5 加盐
- P268 1
- A Type-Safe Event System for Unity3D
- 认识自己——趋利避害生活的能力
- 关于const char *s和char * const s
- Mybatis学习(五)mybatis环境下以接口的方式进行的增删查改
- Laravel 学习笔记 —— 神奇的服务容器
- Linux系统中校验下载文件的完整性方法(MD5,SHA1,PGP)
- JAVA 7 ForkJoin学习笔记
- Excel Sheet Column Title
- 转:Delphi 回调函数及例子
- 学习笔记:python
- 数组指针和指针数组的辨析