QT5+OpenCV美白效果

来源:互联网 发布:恩比德体测数据 编辑:程序博客网 时间:2024/04/28 19:06
皮肤美白的详细内容请参考:对皮肤美白算法的一些研究。


本文采用上面文中的第一种方法即色彩平衡进行美白,首先看了下ImageStone的源码,找到了色彩平衡功能的相关代码如下(源代码在ImageStone中的include\pixelprocessor\PixelProcessorBase.h头文件中):
FCPixelColorBalance (bool bPreLum, TONE_REGION ToneRgn, int cyan_red, int magenta_green, int yellow_blue)    {        m_bPreserveLuminosity = bPreLum ;        int     cyan_red_rgn[3] = {0,0,0},                magenta_green_rgn[3] = {0,0,0},                yellow_blue_rgn[3] = {0,0,0} ;        cyan_red_rgn[ToneRgn] = cyan_red ;        magenta_green_rgn[ToneRgn] = magenta_green ;        yellow_blue_rgn[ToneRgn] = yellow_blue ;        // add for lightening, sub for darkening        PCL_array<double>  highlights_add(256), midtones_add(256), shadows_add(256),                           highlights_sub(256), midtones_sub(256), shadows_sub(256) ;        int     i ;        for (i=0 ; i < 256 ; i++)        {            highlights_add[i] = shadows_sub[255 - i] = (1.075 - 1 / (i / 16.0 + 1)) ;            midtones_add[i] = midtones_sub[i] = 0.667 * (1 - FSquare ((i - 127.0) / 127.0)) ;            shadows_add[i] = highlights_sub[i] = 0.667 * (1 - FSquare ((i - 127.0) / 127.0)) ;        }        // Set the transfer arrays (for speed)        double   * cyan_red_transfer[3], * magenta_green_transfer[3], * yellow_blue_transfer[3] ;        cyan_red_transfer[TONE_SHADOWS] = (cyan_red_rgn[TONE_SHADOWS] > 0) ? shadows_add.get() : shadows_sub.get() ;        cyan_red_transfer[TONE_MIDTONES] = (cyan_red_rgn[TONE_MIDTONES] > 0) ? midtones_add.get() : midtones_sub.get() ;        cyan_red_transfer[TONE_HIGHLIGHTS] = (cyan_red_rgn[TONE_HIGHLIGHTS] > 0) ? highlights_add.get() : highlights_sub.get() ;        magenta_green_transfer[TONE_SHADOWS] = (magenta_green_rgn[TONE_SHADOWS] > 0) ? shadows_add.get() : shadows_sub.get() ;        magenta_green_transfer[TONE_MIDTONES] = (magenta_green_rgn[TONE_MIDTONES] > 0) ? midtones_add.get() : midtones_sub.get() ;        magenta_green_transfer[TONE_HIGHLIGHTS] = (magenta_green_rgn[TONE_HIGHLIGHTS] > 0) ? highlights_add.get() : highlights_sub.get() ;        yellow_blue_transfer[TONE_SHADOWS] = (yellow_blue_rgn[TONE_SHADOWS] > 0) ? shadows_add.get() : shadows_sub.get() ;        yellow_blue_transfer[TONE_MIDTONES] = (yellow_blue_rgn[TONE_MIDTONES] > 0) ? midtones_add.get() : midtones_sub.get() ;        yellow_blue_transfer[TONE_HIGHLIGHTS] = (yellow_blue_rgn[TONE_HIGHLIGHTS] > 0) ? highlights_add.get() : highlights_sub.get() ;        for (i=0 ; i < 256 ; i++)        {            int     r_n = i, g_n = i, b_n = i ;            r_n += (int)(cyan_red_rgn[TONE_SHADOWS] * cyan_red_transfer[TONE_SHADOWS][r_n]);        r_n = FClamp0255(r_n);            r_n += (int)(cyan_red_rgn[TONE_MIDTONES] * cyan_red_transfer[TONE_MIDTONES][r_n]);      r_n = FClamp0255(r_n);            r_n += (int)(cyan_red_rgn[TONE_HIGHLIGHTS] * cyan_red_transfer[TONE_HIGHLIGHTS][r_n]);  r_n = FClamp0255(r_n);            g_n += (int)(magenta_green_rgn[TONE_SHADOWS] * magenta_green_transfer[TONE_SHADOWS][g_n]);        g_n = FClamp0255(g_n);            g_n += (int)(magenta_green_rgn[TONE_MIDTONES] * magenta_green_transfer[TONE_MIDTONES][g_n]);      g_n = FClamp0255(g_n);            g_n += (int)(magenta_green_rgn[TONE_HIGHLIGHTS] * magenta_green_transfer[TONE_HIGHLIGHTS][g_n]);  g_n = FClamp0255(g_n);            b_n += (int)(yellow_blue_rgn[TONE_SHADOWS] * yellow_blue_transfer[TONE_SHADOWS][b_n]);        b_n = FClamp0255(b_n);            b_n += (int)(yellow_blue_rgn[TONE_MIDTONES] * yellow_blue_transfer[TONE_MIDTONES][b_n]);      b_n = FClamp0255(b_n);            b_n += (int)(yellow_blue_rgn[TONE_HIGHLIGHTS] * yellow_blue_transfer[TONE_HIGHLIGHTS][b_n]);  b_n = FClamp0255(b_n);            m_pLookupR[i] = r_n ;            m_pLookupG[i] = g_n ;            m_pLookupB[i] = b_n ;        }    }


由于用色彩平衡来美白要满足以下三项,第一:色阶的三个调整值必须相同或者差异很小,不然输出图片会出现偏色,第二:一定选择中间调;第三:必须不勾选保持明度选项,所以对上面的代码简化后得到如下美白代码:
//定义转换数组    double  highlights_add[256], highlights_sub[256];    double  midtones_add[256], midtones_sub[256];    double  shadows_add[256], shadows_sub[256];//初始化转换数组    for (int i = 0; i < 256; i++)    {        highlights_add[i] = shadows_sub[255 - i] = (1.075 - 1 / ((double) i / 16.0 + 1));        midtones_add[i] = midtones_sub[i] = 0.667 * (1 - (((double) i - 127.0) / 127.0)*(((double) i - 127.0) / 127.0));        shadows_add[i] = highlights_sub[i] = 0.667 * (1 - (((double) i - 127.0) / 127.0)*(((double) i - 127.0) / 127.0));    }//实现相关函数int FMax(const int X, const int Y){    return (X < Y ? Y : X);}int FMin(const int X, const int Y){    return (Y < X ? Y : X);}void BalanceColor(Mat& bitmap,int value){    int red, green, blue;    unsigned char r_lookup[256],g_lookup[256],b_lookup[256];    for (int i = 0; i < 256; i++)    {        red = i;        green = i;        blue = i;        red += (int)( 0.0 * shadows_sub[red] + value * midtones_add[red] + 0.0 * highlights_sub[red]);        red = FMax(0,FMin(0xFF,red));        green += (int)( 0.0 * shadows_sub[green] + value * midtones_add[green] + 0.0 * highlights_sub[green]);        green = FMax(0,FMin(0xFF,green));        blue += (int)( 0.0 * shadows_sub[blue] + value * midtones_add[blue] + 0.0 * highlights_sub[blue]);        blue = FMax(0,FMin(0xFF,blue));        r_lookup[i] = (unsigned char)red;        g_lookup[i] = (unsigned char)green;        b_lookup[i] = (unsigned char)blue;    }    for (int row = 0; row < bitmap.rows; row++)    {        for (int col = 0; col < bitmap.cols; col++)        {            bitmap.at<Vec3b>(row, col)[0] = b_lookup[bitmap.at<Vec3b>(row, col)[0]];            bitmap.at<Vec3b>(row, col)[1] = g_lookup[bitmap.at<Vec3b>(row, col)[1]];            bitmap.at<Vec3b>(row, col)[2] = r_lookup[bitmap.at<Vec3b>(row, col)[2]];        }    }}


附上磨皮加美白的效果图



由于本文算法未对皮肤进行检测,所以美白对象为整张图,效果可能不是很好,有兴趣的可自行加上肤色检测


PS:磨皮加美白完整代码点这里


参考:
图像编辑之色彩平衡 
皮肤检测算法三种,示例与代码
Opencv之人脸肤色检测总结
1 0