如何进行肤色匹配

时间:2013-06-20 07:40:53

标签: opencv image-processing skin

face http://oi44.tinypic.com/2s7771l.jpg(面子)

body http://oi40.tinypic.com/15wewpw.jpg(正文)

嗨,我是图像处理和openCV C / C ++的新手。我想知道是否有可能从第一张图片(脸部)中提取肤色。然后应用于第二张图像(正文)。

换句话说,用户上传他的脸部图像,程序从该图像中提取肤色并将其应用于身体。

谢谢,

阿伊莎

2 个答案:

答案 0 :(得分:3)

要查找皮肤,您可以使用以下公式之一:

1)使用标准化RGB空间:

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

            float normR = static_cast<float>(valueR) / static_cast<float>(valueR + valueG + valueB);
            float normG = static_cast<float>(valueG) / static_cast<float>(valueR + valueG + valueB);
            float normB = static_cast<float>(valueB) / static_cast<float>(valueR + valueG + valueB);

            if ((normB / normG < 1.249) &&
                (( normR + normG + normB ) / ( 3 * normR ) > 0.696 ) &&
                ( 1/3.0 - normB/( normR + normG + normB ) > 0.014 ) &&
                (normG/(3* (normR + normG + normB)) < 0.108 ))
            {
              //pixel is skin
            }
        }
 }

2)在RGB空间中:

for(size_t i = 0; i < m_image->height; ++i)
{
    for(size_t j = 0; j < m_image->width; ++j)
    {
        if (m_image->nChannels == 3)
        {
            int R = (reinterpret_cast<uchar*>(m_image->imageData + i * m_image->widthStep))[j * 3 + 2];
            int G = (reinterpret_cast<uchar*>(m_image->imageData + i * m_image->widthStep))[j * 3 + 1];
            int B = (reinterpret_cast<uchar*>(m_image->imageData + i * m_image->widthStep))[j * 3];

            if (( R > 95) && ( G > 40 ) && ( B > 20 ) &&
                (std::max(R, std::max( G, B) ) - std::min(R, std::min(G, B) ) > 15) &&
                (std::abs(R - G) > 15) && (R > G) && (R > B))
            {
                //skin pixel
            }

        }
    }

3)在YCbCr空间:

for(size_t i = 0; i < m_image->height; ++i)
{
    for(size_t j = 0; j < m_image->width; ++j)
    {
        if (m_image->nChannels == 3)
        {
            int Cr = (reinterpret_cast<uchar*>(image->imageData + i * image->widthStep))[j * 3 + 2];
            int Cb = (reinterpret_cast<uchar*>(image->imageData + i * image->widthStep))[j * 3 + 1];
            int Y = (reinterpret_cast<uchar*>(image->imageData + i * image->widthStep))[j * 3];

            if (( Y > 80 ) && ( Cb > 85 ) && ( Cb < 135 ) &&
                (Cr > 135) && (Cr < 180))
            {
              //skin pixel
            }           
        }
    }
}

答案 1 :(得分:2)

这是一个难以解决的问题,特别是考虑到照明和反射的颜色变化。我之前曾在寻找图像中的皮肤,并且通常YCbCr颜色空间的Cr(色度红色)成分在皮肤上突出显得突出。您可以利用此信息查找皮肤区域。

以下是一些尝试使用颜色定位人体皮肤的文章: 1. Interaction between hands and wearable cameras 2. Markerless inspection of augmented reality objects