混合高斯背景建模

摘自:http://www.rosoo.net/a/opencv/201004/9063.html

 

 

注:以ABS(三星)实现为依据分析出的混合高斯背景建模和更新的过程,不见得是标准高斯建模过程,但过程清晰,具有参考价值。

1. 模型创建:
g_iaABSPixels = (int*)malloc(g_iABSPixelNum * K_MODELS * PMSIZE * 4); //++每个像素维护6个模型,每个模型4个成员(均值,方差,权值,持续时间)
g_lpaABSModel = (int**)malloc(g_iABSPixelNum * K_MODELS * 4); //++每个像素的6个模型连续存放
g_iaABSTotalWeight = (uint16_t*)malloc(g_iABSPixelNum * sizeof(uint16_t));
for(p= 0~g_iABSPixelNum*K_MODELS)
    { g_lpaABSModel[p] = g_iaABSPixels + p*PMSIZE; } //++像素每个模型都指向g_iaABSPixels中实际模型元素

2. 第0帧做背景第一次初始化时,将每个像素的第一个模型初始化为:
g_lpaABSModel[i][0] = pix << 4;              //average
g_lpaABSModel[i][1] = initialVariance << 4; //var (initialVariance全局定义,初始值为12)
g_lpaABSModel[i][2] = 1024 - K_MODELS*32;    //weight
g_lpaABSModel[i][3] = 1024                   //duration: 像素命中该模型的次数累计

像素其他模型初始化为:
g_lpaABSModel[i][0] = 0x7FFFFFF;
g_lpaABSModel[i][1] = initialVariance << 4;
g_lpaABSModel[i][2] = 32;
g_lpaABSModel[i][3] = 0;
同时,该像素各模型的*totalweight = 1024; //更新某个模型权值时,相应要更新该像素totalweight

3. 连续若干帧(16帧)做模型更新建立模型
>获取更新因子: updatefactor = 256 - frameID*16;

>对每帧的每个像素,依次判断是否有高斯模型相匹配,判断依据:
    dist2 = abs(pixel*16 - g_lpaABSModel[match][0]);
    if(dist2*8 < SigmaM8*g_lpaABSModel[match][1])   //全局定义SigmaM8=15
        break;                            

>如果找到匹配模型match,依次更新且只更新第match个模型的各参数:
    //更新模型命中次数
    if(g_lpaABSModel[i][3]<1024) g_lpaABSModel[i][3] += updatefactor;

    //更新模型权值
    g_lpaABSModel[i][2] += updatefactor;
    (*totalweight) += updatefactor; //每个像素各模型权值累加量更新
    if((*totalweight) > 2048)
    {
        (*totalweight) = 0;
        for(i=0; i<K_MODELS; i++)
            { g_lpaABSModel[i][2] = g_lpaABSModel[i][2]>>1;   
               (*totalweight) += g_lpaABSModel[i][2];        }
    }

    //更新均值
    g_lpaABSModel[i][0] = ((g_lpaABSModel[i][0]<<10) - g_lpaABSModel[i][0] + pix*16 + 512) >> 10;

    //更新方差
    if( !(g_lpaABSModel[i][1]<=128 && dist2<g_lpaABSModel[i][1]) && !(g_lpaABSModel[i][1]>=2048 && dist2>g_lpaABSModel[i][1]) )
    {   g_lpaABSModel[i][1] = ( (g_lpaABSModel[i][1]<<10) - (g_lpaABSModel[i][1]<<3) + (dist2<<3) + 512) >> 10;   }
   
    //从上面匹配到的match模型开始做局部排序:
   将当前match权值与match-1,...,0模型权值做插入法排序,保证权值从0到match递减。

>如果没有找到匹配模型,则以当前像素重新初始化最不可能模型g_lpaABSModel[i+K_MODELS-1]:
    (*totalweight) = (*totalweight) - g_lpaABSModel[i+K_MODELS-1][2] + InitialWeight; //初始权值=32
    g_lpaABSModel[i+K_MODELS-1][2] = InitalWeight;
    g_lpaABSModel[i+K_MODELS-1][0] = pixel*16;
    g_lpaABSModel[i+K_MODELS-1][1] = InitialVariance*16;

4. 分析图像并维护背景模型
>获取阈值:bgThr = ((*totalweight) * 11) >> 4;

>提取前3个模型,累加权值,如果超过阈值bgThr, 则提前跳出(通常前3个模型占据了大比重的权值,维持原状(是背景)的可能性最大),总是假设当前点在前一帧是背景点。由此,当匹配后不在这个范围内,则因为g_lpaABSModel[i][3]=0,有理由认为当前点为前景点。
    for(i=0~3) {
       weightSum += g_lpaABSModel[i][2];
       if(g_lpaABSModel[i][3] < 1024) { g_lpaABSModel[i][3] += updatefactor; }
       if((weightSum > bgThr) && i)   { break; }
    }

>剩下模型可以认为是前景点的模型:g_lpaABSModel[i~K_MODELS-1][3] = 0;

>上面按经验将各模型分好类后,接下来将当前点与各模型做匹配,匹配原则是第一个满足均值距离小于方差阈值的对应模型

>如果找到匹配模型,根据匹配持续时间的统计判断该模型是属于前景还是背景:
    if(g_lpaABSModel[i][3] == 0)       cat = FOREPIXEL;
    else if(g_lpaABSModel[i][3] < 600) cat = THEFTPIXEL;
    else cat = BACKGROUND;
然后对各模型权值做归一化处理,对匹配的模型做均值和方差更新,更新系数与建模稍有不同,并做权值排序。

>如果没有找到任何匹配,则以当前像素信息重新初始化最后一个模型g_lpaABSModel[5]:
    (*totalweight) = (*totalweight) - g_lpaABSModel[i][2] + InitialWeight;
    g_lpaABSModel[i][0] = piexl*16;
    g_lpaABSModel[i][1] = InitialVariance*16; //12*16
    g_lpaABSModel[i][2] = InitialWeight; //32
    g_lpaABSModel[i][3] = 0;

>返回cat,得到前景图像

附:以上使用多高斯背景建模的模型创建和模型更新维护过程仅仅是个框架,具体参数的设置和模型维护算法细节上应该具体情况具体分析调整。
       从匹配后像素属类的判断可以看出,一个像素是前景、背景或遗留物点,是根据其所匹配模型的持续统计来决定的,而持续统计又跟模型的命中状况有关,
比如真正的遗留点,命中次数必然多,则持续统计次数大,可以判断为遗留点,而如果持续统计数超过一个很大的值,说明该点已经融入背景中了,统计次数零星的点,可以认为是一闪而过的前景。故通过设置持续次数,可以决定一个前景点融入背景的速度。

你可能感兴趣的:(框架,算法,三星,2010)