使用高斯混合模型进行皮肤检测

Posted

技术标签:

【中文标题】使用高斯混合模型进行皮肤检测【英文标题】:Skin Detection with Gaussian Mixture Models 【发布时间】:2013-06-25 10:05:11 【问题描述】:

我正在根据this article做皮肤检测算法。第 21 页有两个模型:混合高斯皮肤和非皮肤颜色模型。

第一个皮肤检测模型非常出色。 有例子:

1)原图:

2) 皮肤面膜

但是非皮肤模型给出了错误的结果:

这是我的代码:

 ipl_image_wrapper NudityDetector::filterPixelsWithGMM(const float covarinceMatrix[][3], const float meanMatrix[][3], const float weightVector[], const float probValue) const
   
    ipl_image_wrapper mask = cvCreateImage(cvGetSize(m_image.get()), IPL_DEPTH_8U, 1);

    double probability = 0.0;
    float x[3] =  0, 0, 0;

     for(int i = 0; i < m_image.get()->height; ++i)
    
        for(int j = 0; j < m_image.get()->width; ++j)
        
            if (m_image.get()->nChannels == 3)
            
                x[0] = (reinterpret_cast<uchar*>(m_image.get()->imageData + i * m_image.get()->widthStep))[j * 3 + 2];
                x[1] = (reinterpret_cast<uchar*>(m_image.get()->imageData + i * m_image.get()->widthStep))[j * 3 + 1];
                x[2] = (reinterpret_cast<uchar*>(m_image.get()->imageData + i * m_image.get()->widthStep))[j * 3];

                double cov_det = 0.0;
                double power = 0.0;

                double A1 = 0.0;
                double A2 = 0.0;
                double A3 = 0.0;

                probability = 0;

                for (int k = 0; k < 16; ++k)
                
                    cov_det = covarinceMatrix[k][0] * covarinceMatrix[k][1] * covarinceMatrix[k][2];

                    A1 = covarinceMatrix[k][1] * covarinceMatrix[k][2];
                    A2 = covarinceMatrix[k][0] * covarinceMatrix[k][2];
                    A3 = covarinceMatrix[k][0] * covarinceMatrix[k][1];

                    power =(std::pow((x[0] - meanMatrix[k][0]), 2) * A1 +
                            std::pow((x[1] - meanMatrix[k][1]), 2) * A2 +
                            std::pow((x[2] - meanMatrix[k][2]), 2) * A3 ) / (2 * cov_det);

                     probability += 100 * weightVector[k] *std::exp(-power) / (std::pow(2 * M_PI, 3/2) * std::pow(cov_det, 1/2));
                

                if ( probability < probValue)
                
                    (reinterpret_cast<uchar*>(mask.get()->imageData + i * mask.get()->widthStep))[j] = 0;
                
                else
                
                    (reinterpret_cast<uchar*>(mask.get()->imageData + i * mask.get()->widthStep))[j] = 255;
                
            
        
    

    cvDilate(mask.get(), mask.get(), NULL, 2);
    cvErode(mask.get(), mask.get(), NULL, 1);

    return mask;


ipl_image_wrapper NudityDetector::detectSkinWithGMM(const float probValue) const

   //matrices are from article
    ipl_image_wrapper mask = filterPixelsWithGMM(COVARIANCE_SKIN_MATRIX, MEAN_SKIN_MATRIX, SKIN_WEIGHT_VECTOR, probValue);

    return mask;
 

ipl_image_wrapper NudityDetector::detectNonSkinWithGMM(const float probValue) const

    //matrices are from article
   ipl_image_wrapper mask = filterPixelsWithGMM(COVARIANCE_NON_SKIN_MATRIX, MEAN_NON_SKIN_MATRIX, NON_SKIN_WEIGHT_VECTOR, probValue);

   return mask;
 

我做错了什么?也许我误解了tre文章的含义?还是我在代码中翻译了错误的公式?

提前感谢您!

【问题讨论】:

【参考方案1】:

其实结果似乎没有什么问题,non-skin模型正确的将non-skin区域识别为255,将skin region正确识别为0。您可能只需将参数probValue调低即可得到去除一些假阴性(小的非皮肤区域)

GMM 可能不是皮肤检测的有效方法,您可以使用一些边缘强度信息作为正则化参数,以便检测到的区域不会被分割。

【讨论】:

以上是关于使用高斯混合模型进行皮肤检测的主要内容,如果未能解决你的问题,请参考以下文章

使用高斯混合模型对图像进行聚类

如何使用高斯混合模型进行聚类?

opencv:使用高斯混合模型(GMM)源码对视频进行背景差分法

高斯混合模型

无监督学习高斯混合模型

Coursera高斯混合模型