zoukankan      html  css  js  c++  java
  • 混合高斯背景建模原理及实现

    转自:http://blog.csdn.net/jinshengtao/article/details/26278725

    一、理论

    混合高斯背景建模是基于像素样本统计信息的背景表示方法,利用像素在较长时间内大量样本值的概率密度等统计信息(如模式数量、每个模式的均值和标准差)表示背景,然后使用统计差分(如3σ原则)进行目标像素判断,可以对复杂动态背景进行建模,计算量较大。

    在混合高斯背景模型中,认为像素之间的颜色信息互不相关,对各像素点的处理都是相互独立的。对于视频图像中的每一个像素点,其值在序列图像中的变化可看作是不断产生像素值的随机过程,即用高斯分布来描述每个像素点的颜色呈现规律【单模态(单峰),多模态(多峰)】。

    对于多峰高斯分布模型,图像的每一个像素点按不同权值的多个高斯分布的叠加来建模,每种高斯分布对应一个可能产生像素点所呈现颜色的状态,各个高斯分布的权值和分布参数随时间更新。当处理彩色图像时,假定图像像素点R、G、B三色通道相互独立并具有相同的方差。对于随机变量X的观测数据集{x1,x2,…,xN},xt=(rt,gt,bt)为t时刻像素的样本,则单个采样点xt其服从的混合高斯分布概率密度函数:

    其中k为分布模式总数,η(xt,μi,tτi,t)为t时刻第i个高斯分布,μi,t为其均值,τi,t为其协方差矩阵,δi,t为方差,I为三维单位矩阵,ωi,tt时刻第i个高斯分布的权重。

    详细算法流程:

    二、代码实现(我还没验证,不知效果)

    // my_mixgaussians.cpp : 定义控制台应用程序的入口点。  
    //  
     
    #include "stdafx.h"  
    #include "cv.h"  
    #include "highgui.h"  
      
    int _tmain(int argc, _TCHAR* argv[])  
    {  
        CvCapture *capture=cvCreateFileCapture("test.avi");  
        IplImage *mframe,*current,*frg,*test;  
        int *fg,*bg_bw,*rank_ind;  
        double *w,*mean,*sd,*u_diff,*rank;  
        int C,M,sd_init,i,j,k,m,rand_temp=0,rank_ind_temp=0,min_index=0,x=0,y=0,counter_frame=0;  
        double D,alph,thresh,p,temp;  
        CvRNG state;  
        int match,height,width;  
        mframe=cvQueryFrame(capture);  
      
        frg = cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);  
        current = cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);  
        test = cvCreateImage(cvSize(mframe->width,mframe->height),IPL_DEPTH_8U,1);  
          
        C = 4;                      //number of gaussian components (typically 3-5)  
        M = 4;                      //number of background components  
        sd_init = 6;                //initial standard deviation (for new components) var = 36 in paper  
        alph = 0.01;                //learning rate (between 0 and 1) (from paper 0.01)  
        D = 2.5;                    //positive deviation threshold  
        thresh = 0.25;              //foreground threshold (0.25 or 0.75 in paper)  
        p = alph/(1/C);         //initial p variable (used to update mean and sd)  
      
        height=current->height;width=current->widthStep;  
          
        fg = (int *)malloc(sizeof(int)*width*height);                   //foreground array  
        bg_bw = (int *)malloc(sizeof(int)*width*height);                //background array  
        rank = (double *)malloc(sizeof(double)*1*C);                    //rank of components (w/sd)  
        w = (double *)malloc(sizeof(double)*width*height*C);            //weights array  
        mean = (double *)malloc(sizeof(double)*width*height*C);         //pixel means  
        sd = (double *)malloc(sizeof(double)*width*height*C);           //pixel standard deviations  
        u_diff = (double *)malloc(sizeof(double)*width*height*C);       //difference of each pixel from mean  
          
        for (i=0;i<height;i++)  
        {  
            for (j=0;j<width;j++)  
            {  
                for(k=0;k<C;k++)  
                {  
                    mean[i*width*C+j*C+k] = cvRandReal(&state)*255;  
                    w[i*width*C+j*C+k] = (double)1/C;  
                    sd[i*width*C+j*C+k] = sd_init;  
                }  
            }  
        }  
      
        while(1){  
            rank_ind = (int *)malloc(sizeof(int)*C);  
            cvCvtColor(mframe,current,CV_BGR2GRAY);  
            // calculate difference of pixel values from mean  
            for (i=0;i<height;i++)  
            {  
                for (j=0;j<width;j++)  
                {  
                    for (m=0;m<C;m++)  
                    {  
                        u_diff[i*width*C+j*C+m] = abs((uchar)current->imageData[i*width+j]-mean[i*width*C+j*C+m]);  
                    }  
                }  
            }  
            //update gaussian components for each pixel  
            for (i=0;i<height;i++)  
            {  
                for (j=0;j<width;j++)  
                {  
                    match = 0;  
                    temp = 0;  
                    for(k=0;k<C;k++)  
                    {  
                        if (abs(u_diff[i*width*C+j*C+k]) <= D*sd[i*width*C+j*C+k])      //pixel matches component  
                        {  
                             match = 1;                                                 // variable to signal component match  
                               
                             //update weights, mean, sd, p  
                             w[i*width*C+j*C+k] = (1-alph)*w[i*width*C+j*C+k] + alph;  
                             p = alph/w[i*width*C+j*C+k];                    
                             mean[i*width*C+j*C+k] = (1-p)*mean[i*width*C+j*C+k] + p*(uchar)current->imageData[i*width+j];  
                             sd[i*width*C+j*C+k] =sqrt((1-p)*(sd[i*width*C+j*C+k]*sd[i*width*C+j*C+k]) + p*(pow((uchar)current->imageData[i*width+j] - mean[i*width*C+j*C+k],2)));  
                        }else{  
                            w[i*width*C+j*C+k] = (1-alph)*w[i*width*C+j*C+k];           // weight slighly decreases  
                        }  
                        temp += w[i*width*C+j*C+k];  
                    }  
                      
                    for(k=0;k<C;k++)  
                    {  
                        w[i*width*C+j*C+k] = w[i*width*C+j*C+k]/temp;  
                    }  
                  
                    temp = w[i*width*C+j*C];  
                    bg_bw[i*width+j] = 0;  
                    for (k=0;k<C;k++)  
                    {  
                        bg_bw[i*width+j] = bg_bw[i*width+j] + mean[i*width*C+j*C+k]*w[i*width*C+j*C+k];  
                        if (w[i*width*C+j*C+k]<=temp)  
                        {  
                            min_index = k;  
                            temp = w[i*width*C+j*C+k];  
                        }  
                        rank_ind[k] = k;  
                    }  
      
                    test->imageData[i*width+j] = (uchar)bg_bw[i*width+j];  
      
                    //if no components match, create new component  
                    if (match == 0)  
                    {  
                        mean[i*width*C+j*C+min_index] = (uchar)current->imageData[i*width+j];  
                        //printf("%d ",(uchar)bg->imageData[i*width+j]);  
                        sd[i*width*C+j*C+min_index] = sd_init;  
                    }  
                    for (k=0;k<C;k++)  
                    {  
                        rank[k] = w[i*width*C+j*C+k]/sd[i*width*C+j*C+k];  
                        //printf("%f ",w[i*width*C+j*C+k]);  
                    }  
      
                    //sort rank values  
                    for (k=1;k<C;k++)  
                    {  
                        for (m=0;m<k;m++)  
                        {  
                            if (rank[k] > rank[m])  
                            {  
                                //swap max values  
                                rand_temp = rank[m];  
                                rank[m] = rank[k];  
                                rank[k] = rand_temp;  
      
                                //swap max index values  
                                rank_ind_temp = rank_ind[m];  
                                rank_ind[m] = rank_ind[k];  
                                rank_ind[k] = rank_ind_temp;  
                            }  
                        }  
                    }  
      
                    //calculate foreground  
                    match = 0;k = 0;  
                    //frg->imageData[i*width+j]=0;  
                    while ((match == 0)&&(k<M)){  
                        if (w[i*width*C+j*C+rank_ind[k]] >= thresh)  
                            if (abs(u_diff[i*width*C+j*C+rank_ind[k]]) <= D*sd[i*width*C+j*C+rank_ind[k]]){  
                                frg->imageData[i*width+j] = 0;  
                                match = 1;  
                            }  
                            else  
                                frg->imageData[i*width+j] = (uchar)current->imageData[i*width+j];       
                        k = k+1;  
                    }  
                }  
            }         
      
            mframe = cvQueryFrame(capture);  
            cvShowImage("fore",frg);  
            cvShowImage("back",test);  
            char s=cvWaitKey(33);  
            if(s==27) break;  
            free(rank_ind);  
        }  
          
        free(fg);free(w);free(mean);free(sd);free(u_diff);free(rank);  
        cvNamedWindow("back",0);  
        cvNamedWindow("fore",0);  
        cvReleaseCapture(&capture);  
        cvDestroyWindow("fore");  
        cvDestroyWindow("back");  
        return 0;  
    }  

    (原作者)实验结果:

    前景:

    背景:

  • 相关阅读:
    IE6中布局常见问题
    -bash: grunt-cli: command not found
    字符长度
    Mac下safari、chrome打开开发者工具快捷键
    line-height:150%和line-height:1.5的区别
    JavaScript中的apply()、call()、bind()
    JavaScript中的 this
    JavaScript中的var与作用域
    onload与ready的区别
    浏览器的同源策略
  • 原文地址:https://www.cnblogs.com/wyuzl/p/6868093.html
Copyright © 2011-2022 走看看