How to perform skin tone matching

2020-03-26 02:40发布

face ( face )

body ( body )

Hi, i am new to image processing and openCV C/C++. I am wondering that is it possible to extract skin tone from the first image (face). And then applied to the second image (body).

In other words, user upload his face image and the program extract the skin tone from that image and apply it to the body.

Thanks,

Aisha

2条回答
2楼-- · 2020-03-26 03:10

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
            }           
        }
    }
}
查看更多
仙女界的扛把子
3楼-- · 2020-03-26 03:26

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

查看更多
登录 后发表回答