Color Transfer Between Image
Color Transfer Between Images算法中,給定兩張圖檔source_img和target_img。該算法可以把source_img中的顔色遷移到target_img中。
算法主要思路為:
- 給定輸入圖像source_img和target_img
- 把source_img和target_img轉換到Lab顔色空間,轉換後圖像為source_lab和target_lab
- 分别計算source_Lab和target_lab三個通道的均值和标準差
- 根據論文中的公式,分别計算三通道的變換值:

5. 把Lab空間的結果圖像再轉換到RGB空間,并顯示
Lab轉RGB空間和RGB轉LAB空間,可以參考之前寫的博文:RGB與Lab顔色空間互相轉換
算法關鍵代碼實作:
RGB2Lab(source_img,source_lab);
RGB2Lab(target_img,target_lab);
source_Mean = ConputerMean(source_lab,source_height,source_width,source_line_byte);
target_Mean = ConputerMean(target_lab,target_height,target_width,target_line_byte);
source_Labvar = ConputerVar(source_height,source_width,source_Mean);
target_Labvar = ConputerVar(target_height,target_width,target_Mean);
Color_Transform_Func(target_lab,source_Labvar,target_Labvar,source_Mean,target_Mean,target_height,target_width,target_line_byte);
bmp = Lab2RGB(target_img,target_lab);
fwrite(bmp, target_line_byte*target_height, 1, Color_Transform_BMP_fp);
fclose(Color_Transform_BMP_fp);
free(Color_Transform_BMP);
free(bmp);
return 0;
計算均值和方差關鍵代碼:
LABMEAN ConputerMean(float *lab_img,DWORD height,DWORD width,T_U32 line_byte)
{
double LMean,aMean,bMean,SumL,SumA,SumB,SumL2,SumA2,SumB2,TmpL,TmpA,TmpB,size,l,a,b;
DWORD i,j,index;
LABMEAN labMean = {0};
LMean = 0.0;
aMean =0;
bMean=0.0;
SumL = 0;
SumA = 0;
SumB = 0;
SumL2 = 0.0;
SumA2 = 0.0;
SumB2 = 0.0;
TmpL = 0;
TmpA = 0.0;
TmpB = 0;
size = width*height;
for(i = 0; i < height;i++)
{
for(j = 0;j < width;j++)
{
index = i*line_byte+3*j;
TmpL = lab_img[index+0];
SumL += TmpL;
SumL2 += TmpL*TmpL;
TmpA = lab_img[index+1];
SumA += TmpA;
SumA2 += TmpA*TmpA;
TmpB = lab_img[index+2];
SumB += TmpB;
SumB2 += TmpB*TmpB;
}
}
LMean = SumL/(size);
aMean = SumA/(size);
bMean = SumB/(size);
labMean.MeanL = LMean;
labMean.MeanA = aMean;
labMean.MeanB = bMean;
labMean.SumL = SumL;
labMean.SumA = SumA;
labMean.SumB = SumB;
labMean.SumL2 = SumL2;
labMean.SumA2 = SumA2;
labMean.SumB2 = SumB2;
return labMean;
}
LABVAR ConputerVar(DWORD height,DWORD width,LABMEAN labMean)
{
double LVar,aVar,bVar,size;
LABVAR labvar = {0};
LVar = 0.0;
aVar = 0.;
bVar = 0.0;
size = width*height;
LVar = (labMean.SumL2-(labMean.SumL*labMean.SumL)/size)/size;
aVar = (labMean.SumA2-(labMean.SumA*labMean.SumA)/size)/size;
bVar = (labMean.SumB2-(labMean.SumB*labMean.SumB)/size)/size;
LVar = sqrt(LVar);
aVar = sqrt(aVar);
bVar = sqrt(bVar);
labvar.VarL = LVar;
labvar.VarA = aVar;
labvar.VarB = bVar;
return labvar;
}
顔色轉換關鍵代碼實作:
void Color_Transform_Func(float *lab_img,LABVAR source_var,LABVAR target_var,LABMEAN source_mean,LABMEAN target_mean,DWORD height,DWORD width,T_U32 line_byte)
{
int i,j,index;
for(i = 0; i < height;i++)
{
for(j = 0;j < width;j++)
{
index = i*line_byte+3*j;
lab_img[index+0] -= target_mean.MeanL;
lab_img[index+1] -= target_mean.MeanA;
lab_img[index+2] -= target_mean.MeanB;
lab_img[index+0] = (target_var.VarL/source_var.VarL)*lab_img[index+0];
lab_img[index+1] = (target_var.VarA/source_var.VarA)*lab_img[index+1];
lab_img[index+2] = (target_var.VarB/source_var.VarB)*lab_img[index+2];
lab_img[index+0] += source_mean.MeanL;
lab_img[index+1] += source_mean.MeanA;
lab_img[index+2] += source_mean.MeanB;
}
}
}
圖像結果:
左圖為source_img,又圖為target_img
結果圖像