【2017-04-01:完整项目文件GitHub】
皮肤美白的详细内容请参考:对皮肤美白算法的一些研究。
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 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(row, col)[0] = b_lookup[bitmap.at(row, col)[0]];
bitmap.at(row, col)[1] = g_lookup[bitmap.at(row, col)[1]];
bitmap.at(row, col)[2] = r_lookup[bitmap.at(row, col)[2]];
}
}
}
附上磨皮加美白的效果图
PS:磨皮加美白完整代码点这里