单高斯背景建模

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_22562949/article/details/46445891

这些原理和算法流程,转自别人的博客,代码是自己实现的。

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

猜你喜欢

转载自blog.csdn.net/qq_22562949/article/details/46445891