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');
    

      

  • 相关阅读:
    主从数据库
    Linux 安装 mysql
    centos7.5上安装go1.13.4
    Linux 安装php
    CENTOS7下安装redis
    CentOS 7安装Etherpad(在线协作编辑)
    nginx《一安装》
    springboot中redis取缓存类型转换异常
    linux安装mysql
    linux上传下载文件(转载https://www.jb51.net/article/143112.htm)
  • 原文地址:https://www.cnblogs.com/molakejin/p/5457303.html
Copyright © 2011-2022 走看看