How to perform skin tone matching

一笑奈何 提交于 2019-12-01 08:10:43

For finding skin you can use one of this formulas:

1) With normilized RGB space:

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) in RGB space:

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) in YCrCb space:

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
            }           
        }
    }
}

This is a hard problem to solve, especially given the variation of colours depending on lighting and reflection. I have worked previously on finding skin in images, and generally the Cr (chroma red) component of the YCbCr colour space stands out prominently on skin. You might be able to exploit this information to find skin regions.

Here are a couple of papers that attempt to use colour for locating human skin: 1. Interaction between hands and wearable cameras 2. Markerless inspection of augmented reality objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!