zoukankan      html  css  js  c++  java
  • paper 62:高斯混合模型(GMM)参数优化及实现

    高斯混合模型(GMM)参数优化及实现 (< xmlnamespace prefix ="st1" ns ="urn:schemas-microsoft-com:office:smarttags" />2010-11-13

    高斯混合模型概述< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />

    高斯密度函数估计是一种参数化模型。有单高斯模型(Single Gaussian Model, SGM)和高斯混合模型(Gaussian mixture modelGMM)两类。类似于聚类,根据高斯概率密度函数(PDF,见公式1)参数的不同,每一个高斯模型可以看作一种类别,输入一个样本< xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" /> ,即可通过PDF计算其值,然后通过一个阈值来判断该样本是否属于高斯模型。很明显,SGM适合于仅有两类别问题的划分,而GMM由于具有多个模型,划分更为精细,适用于多类别的划分,可以应用于复杂对象建模。

    下面以视频前景分割应用场景为例,说明SGMGMM在应用上的优劣比较:

    l        SGM需要进行初始化,如在进行视频背景分割时,这意味着如果人体在前几帧就出现在摄像头前,人体将会被初始化为背景,而使模型无法使用;

    l        SGM只能进行微小性渐变,而不可突变。如户外亮度随时间的渐变是可以适应的,如果在明亮的室内突然关灯,单高斯模型就会将整个室内全部判断为前景。又如,若在监控范围内开了一辆车,并在摄像头下开始停留。由于与模型无法匹配,车会一直被视为前景。当车过很长时间离去时,由于车停留点的亮度发生了很大的变化,因此已经无法与先前的背景模型相匹配;

    l        SGM无法适应背景有多个状态,如窗帘,风吹的树叶。单高斯模型无法表示这种情况,而使得前背景检测混乱,而GMM能够很好地描述不同状态;

    l        相对于单高斯模型的自适应变化,混合高斯模型的自适应变化要健壮的多。它能解决单高斯模型很多不能解决的问题。如无法解决同一样本点的多种状态,无法进行模型状态转化等。

    2 理论说明部分

    因博客中无法编辑公式,故详细文档见这里。代码如下:

    源码

    3.1 单高斯模型

    下面代码实现了SGM,并实现了人脸肤色检测。其中图像处理、矩阵运算采用了openCV库函数

    /*****************************************************************************
    
           Single Gaussian Model for skin color extraction
    
           Param:
    
                  img -- input image to extract the face region
    
                  skinImg -- result
    
    *****************************************************************************/
    
    void CSkinColor::RunSGM(IplImage *img, IplImage **skinImg)
    
    {
    
           if (img == NULL) return -1;
    
           //////////////////////////////////////////////////////////////////////////
    
           // 以下参数一组(117.4361,156.5599)来自源码 light2,与文章《王航宇:基于 YCbCr 高斯肤色模型的
    
           // 人脸检测技术研究》相同,另一组来自源码“肤色检测正式版”(103.0056, 140.1309)
    
           double M[]={103.0056, 140.1309}/*{117.4361,156.5599}*/;//M 为肤色在 YCbCr 颜色空间的样本均值(Cb, Cr),经验值
    
           double C[2][2]={{160.1301,12.1430},//C 为肤色相似度模型的协方差矩阵,同上为经验值
    
                  {12.1430,299.4574}};// 注:因为运算仅需要该矩阵的逆矩阵值,故该值没有使用,仅作参考
    
           double invC[2][2]={0.0077 ,-0.0041,-0.0041 ,0.0047
    
           };//Ct 为C的逆矩阵值,由matlab计算而得
    
           //////////////////////////////////////////////////////////////////////////
    
           IplImage* pImg = img;
    
           double CrMean=0,CbMean=0,YMean=0;
    
           // 1 颜色转换:BGR->YCrCb
    
           IplImage*imgYCrCb=cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,3);// YCrCb图像
    
           cvCvtColor(pImg, imgYCrCb, CV_BGR2YCrCb);// 第0,1,2层分别为Y,Cr,Cb
    
          
    
           IplImage *imgY = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,1);// YCrCb图像
    
           IplImage *imgCr = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,1);// YCrCb图像
    
           IplImage *imgCb = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U,1);// YCrCb图像
    
           IplImage *imgY32 = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_32F,1);// YCrCb图像
    
           IplImage *imgCr32 = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_32F,1);// YCrCb图像
    
           IplImage *imgCb32 = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_32F,1);// YCrCb图像
    
           cvSplit(imgYCrCb, imgY, imgCr, imgCb, NULL);
    
           cvConvert(imgY, imgY32);
    
           cvConvert(imgCr, imgCr32);
    
           cvConvert(imgCb, imgCb32);
    
           //////////////////////////////////////////////////////////////////////////
    
           // 2 根据Sigle Gaussian Model计算颜色模型
    
           IplImage *PCbCr=cvCreateImage(cvGetSize(pImg), IPL_DEPTH_32F, 1);//YCrCb颜色模型
    
           IplImage *tempA=cvCreateImage(cvGetSize(pImg), IPL_DEPTH_32F, 1);//YCrCb颜色模型
    
           IplImage *tempB=cvCreateImage(cvGetSize(pImg), IPL_DEPTH_32F, 1);//YCrCb颜色模型
    
           cvSubS(imgCb32, cvScalar(M[0]), imgCb32);// x-m
    
           cvSubS(imgCr32, cvScalar(M[1]), imgCr32);// x-m
    
           cvAddWeighted(imgCb32, invC[0][0], imgCr32, invC[1][0], 0, tempA);
    
           cvAddWeighted(imgCb32, invC[0][1], imgCr32, invC[1][1], 0, tempB);
    
           cvMul(imgCb32, tempA, tempA, -0.5);
    
           cvMul(imgCr32, tempB, tempB, -0.5);
    
           cvAdd(tempA, tempB, PCbCr);
    
           cvExp(PCbCr, PCbCr);
    
           double max_val=0,min_val=0;
    
           cvMinMaxLoc(PCbCr,&min_val,&max_val);
    
           IplImage *proImg=cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U, 1);//YCrCb颜色模型
    
           double a=255/(max_val);
    
           cvConvertScaleAbs(PCbCr,proImg,a,0);
    
           m_proimg = cvCloneImage(proImg);
    
          
    
           if ((*skinImg)!=NULL) cvReleaseImage(skinImg);
    
           *skinImg = cvCreateImage(cvGetSize(pImg),IPL_DEPTH_8U, 1);//肤色结果
    
           // 释放内存
    
           cvReleaseImage(&proImg);
    
           cvReleaseImage(&imgYCrCb);
    
           cvReleaseImage(&imgY);
    
           cvReleaseImage(&imgCr);
    
           cvReleaseImage(&imgCb);
    
           cvReleaseImage(&imgY32);
    
           cvReleaseImage(&imgCr32);
    
           cvReleaseImage(&imgCb32);
    
           cvReleaseImage(&PCbCr);
    
           cvReleaseImage(&tempA);
    
           cvReleaseImage(&tempB);
    
    }
    

      

     

    3.1高斯混合模型

    1)以下matlab代码实现了高斯混合模型:

    function [Alpha, Mu, Sigma] = GMM_EM(Data, Alpha0, Mu0, Sigma0)
    
    %% EM 迭代停止条件
    
    loglik_threshold = 1e-10;
    
    %% 初始化参数
    
    [dim, N] = size(Data);
    
    M = size(Mu0,2);
    
    loglik_old = -realmax;
    
    nbStep = 0;
    
     
    
    Mu = Mu0;
    
    Sigma = Sigma0;
    
    Alpha = Alpha0;
    
    Epsilon = 0.0001;
    
    while (nbStep < 1200)
    
      nbStep = nbStep+1;
    
      %% E-步骤 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
      for i=1:M
    
        % PDF of each point
    
        Pxi(:,i) = GaussPDF(Data, Mu(:,i), Sigma(:,:,i));         
    
      end
    
     
    
      % 计算后验概率 beta(i|x)
    
      Pix_tmp = repmat(Alpha,[N 1]).*Pxi;
    
      Pix = Pix_tmp ./ (repmat(sum(Pix_tmp,2),[1 M])+realmin);
    
      Beta = sum(Pix);
    
      %% M-步骤 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
      for i=1:M
    
        % 更新权值
    
        Alpha(i) = Beta(i) / N;
    
        % 更新均值
    
        Mu(:,i) = Data*Pix(:,i) / Beta(i);
    
        % 更新方差
    
        Data_tmp1 = Data - repmat(Mu(:,i),1,N);
    
        Sigma(:,:,i) = (repmat(Pix(:,i)',dim, 1) .* Data_tmp1*Data_tmp1') / Beta(i);
    
        %% Add a tiny variance to avoid numerical instability
    
        Sigma(:,:,i) = Sigma(:,:,i) + 1E-5.*diag(ones(dim,1));
    
      end
    
     
    
    %  %% Stopping criterion 1 %%%%%%%%%%%%%%%%%%%%
    
    %  for i=1:M
    
        %Compute the new probability p(x|i)
    
    %    Pxi(:,i) = GaussPDF(Data, Mu(:,i), Sigma(i));
    
    %  end
    
      %Compute the log likelihood
    
    %  F = Pxi*Alpha';
    
    %  F(find(F<realmin)) = realmin;
    
    %  loglik = mean(log(F));
    
      %Stop the process depending on the increase of the log likelihood
    
    %  if abs((loglik/loglik_old)-1) < loglik_threshold
    
    %    break;
    
    %  end
    
    %  loglik_old = loglik;
    
     
    
      %% Stopping criterion 2 %%%%%%%%%%%%%%%%%%%%
    
      v = [sum(abs(Mu - Mu0)), abs(Alpha - Alpha0)];
    
      s = abs(Sigma-Sigma0);
    
      v2 = 0;
    
      for i=1:M
    
        v2 = v2 + det(s(:,:,i));
    
      end
    
     
    
      if ((sum(v) + v2) < Epsilon)
    
        break;
    
      end
    
      Mu0 = Mu;
    
      Sigma0 = Sigma;
    
      Alpha0 = Alpha;
    
    end
    
    nbStep
    

      

     

    2)以下代码根据高斯分布函数计算每组数据的概率密度,被GMM_EM函数所调用

    function prob = GaussPDF(Data, Mu, Sigma)
    
    %
    
    % 根据高斯分布函数计算每组数据的概率密度 Probability Density Function (PDF)
    
    % 输入 -----------------------------------------------------------------
    
    %   o Data:  D x N ,N个D维数据
    
    %   o Mu:    D x 1 ,M个Gauss模型的中心初始值
    
    %   o Sigma: M x M ,每个Gauss模型的方差(假设每个方差矩阵都是对角阵,
    
    %                                   即一个数和单位矩阵的乘积)
    
    % Outputs ----------------------------------------------------------------
    
    %   o prob:  1 x N array representing the probabilities for the
    
    %            N datapoints.    
    
    [dim,N] = size(Data);
    
    Data = Data' - repmat(Mu',N,1);
    
    prob = sum((Data*inv(Sigma)).*Data, 2);
    
    prob = exp(-0.5*prob) / sqrt((2*pi)^dim * (abs(det(Sigma))+realmin));
    

      

     

    3)以下是演示代码demo1.m

    % 高斯混合模型参数估计示例 (基于 EM 算法)
    
    % 2010 年 11 月 9 日
    
    [data, mu, var, weight] = CreateSample(M, dim, N);  // 生成测试数据
    
    [Alpha, Mu, Sigma] = GMM_EM(Data, Priors, Mu, Sigma)
    

      

     

    4)以下是测试数据生成函数,为demo1.m所调用:

    function [data, mu, var, weight] = CreateSample(M, dim, N)
    
    % 生成实验样本集,由M组正态分布的数据构成
    
    % % GMM模型的原理就是仅根据数据估计参数:每组正态分布的均值、方差,
    
    % 以及每个正态分布函数在GMM的权重alpha。
    
    % 在本函数中,这些参数均为随机生成,
    
    %
    
    % 输入
    
    %   M    : 高斯函数个数
    
    %   dim  : 数据维数
    
    %   N    : 数据总个数
    
    % 返回值
    
    %   data : dim-by-N, 每列为一个数据
    
    %   miu  : dim-by-M, 每组样本的均值,由本函数随机生成
    
    %   var  : 1-by-M, 均方差,由本函数随机生成
    
    %   weight: 1-by-M, 每组的权值,由本函数随机生成
    
    % ----------------------------------------------------
    
    %
    
    % 随机生成不同组的方差、均值及权值
    
    weight = rand(1,M);
    
    weight = weight / norm(weight, 1); % 归一化,保证总合为1
    
    var = double(mod(int16(rand(1,M)*100),10) + 1);  % 均方差,取1~10之间,采用对角矩阵
    
    mu = double(round(randn(dim,M)*100));            % 均值,可以有负数
    
     
    
    for(i = 1: M)
    
      if (i ~= M)
    
        n(i) = floor(N*weight(i));
    
      else
    
        n(i) = N - sum(n);
    
      end
    
    end
    
     
    
    % 以标准高斯分布生成样本值,并平移到各组相应均值和方差
    
    start = 0;
    
    for (i=1:M)
    
      X = randn(dim, n(i));
    
      X = X.* var(i) + repmat(mu(:,i),1,n(i));
    
      data(:,(start+1):start+n(i)) = X;
    
      start = start + n(i);
    
    end
    
    save('d:data.mat', 'data');
    

      

  • 相关阅读:
    【codecombat】 试玩全攻略 第九关 循环又循环
    【codecombat】 试玩全攻略 第十三关 已知敌人
    【codecombat】 试玩全攻略 第十一关 再次迷宫经历
    【codecombat】 试玩全攻略 第六关 cell commentary
    【codecombat】 试玩全攻略 第八关 火舞
    【codecombat】 试玩全攻略 第十二关 恐惧之门
    【codecombat】 试玩全攻略 第十四关 已知敌人
    苹果apns推送总结
    Xcode 提升速度小技巧
    UITextField 限制输入字数
  • 原文地址:https://www.cnblogs.com/molakejin/p/5457303.html
Copyright © 2011-2022 走看看