天天看點

Color Transfer Between Image

Color Transfer Between Image

      Color Transfer Between Images算法中,給定兩張圖檔source_img和target_img。該算法可以把source_img中的顔色遷移到target_img中。

算法主要思路為:

  1. 給定輸入圖像source_img和target_img
  2. 把source_img和target_img轉換到Lab顔色空間,轉換後圖像為source_lab和target_lab
  3. 分别計算source_Lab和target_lab三個通道的均值和标準差
  4. 根據論文中的公式,分别計算三通道的變換值:
Color Transfer Between Image

         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;

		}
	}

}
           

圖像結果:

Color Transfer Between Image
Color Transfer Between Image

     左圖為source_img,又圖為target_img

Color Transfer Between Image

結果圖像