Color Transfer between Images code实现

时间:2022-01-08 22:45:28

上计算机视觉课老师布置的作业实现论文:Color Transfer between Images

基本思路是:

1.给定srcImg和targetImg

2.将RGB空间转为Lab空间

3.根据论文中公式:

Color Transfer between Images code实现

计算每一个像素点

4.将resultImg转回到RGB空间显示

效果图:

Color Transfer between Images code实现 Color Transfer between Images code实现 Color Transfer between Images code实现

Color Transfer between Images code实现 Color Transfer between Images code实现 Color Transfer between Images code实现

见代码:

 #include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <math.h>
using namespace std;
using namespace cv; class ColorTransfer
{
public:
Mat resultImg; ColorTransfer(Mat src, Mat target)
{
src.convertTo(srcImg_32F, CV_32FC3,1.0f/.f);//这里切记要类型转换下
target.convertTo(targetImg_32F, CV_32FC3, 1.0f/255.0f);
resultImg = srcImg_32F; //将结果先初始化为源图像 srcImg_Lab = RGBToLab(srcImg_32F);
targetImg_Lab = RGBToLab(targetImg_32F);
srcMeans = computeMeans(srcImg_Lab);
targetMeans = computeMeans(targetImg_Lab);
srcVariances = computeVariances(srcImg_Lab, srcMeans);
targetVariances = computeVariances(targetImg_Lab, targetMeans);
computeResult();
} private:
//读入的RGB图像
Mat srcImg_32F;
Mat targetImg_32F;
//转换后的Lab空间图像
Mat srcImg_Lab;
Mat targetImg_Lab;
//计算得到的均值和方差
Vector<double> srcMeans;
Vector<double> targetMeans;
Vector<double> srcVariances;
Vector<double> targetVariances; //RGB转换到Lab空间
Mat RGBToLab(Mat m)
{
Mat_<Vec3f> I = m;
for(int i=;i<I.rows;++i)
{
for(int j=;j<I.cols;++j)
{
double L = 0.3811*I(i,j)[] + 0.5783*I(i,j)[] + 0.0402*I(i,j)[];
double M = 0.1967*I(i,j)[] + 0.7244*I(i,j)[] + 0.0782*I(i,j)[];
double S = 0.0241*I(i,j)[] + 0.1288*I(i,j)[] + 0.8444*I(i,j)[];
if(L == ) L = ;
if(M == ) M = ;
if(S == ) S = ;
L = log(L);
M = log(M);
S = log(S); I(i,j)[] = (L+M+S) / sqrt(3.0);
I(i,j)[] = (L+M-*S) / sqrt(6.0);
I(i,j)[] = (L-M) / sqrt(2.0);
}
} return I;
} //Lab转换到RGB空间
Mat LabToRGB(Mat m)
{
Mat_<Vec3f> I = m;
for(int i=;i<I.rows;++i)
for(int j=;j<I.cols;++j)
{
double L = I(i,j)[]/sqrt(3.0) + I(i,j)[]/sqrt(6.0) + I(i,j)[]/sqrt(2.0);
double M = I(i,j)[]/sqrt(3.0) + I(i,j)[]/sqrt(6.0) - I(i,j)[]/sqrt(2.0);
double S = I(i,j)[]/sqrt(3.0) - *I(i,j)[]/sqrt(6.0); L = exp(L);
M = exp(M);
S = exp(S); I(i,j)[] = 4.4679*L - 3.5873*M + 0.1193*S;
I(i,j)[] = -1.2186*L + 2.3809*M - 0.1624*S;
I(i,j)[] = 0.0497*L - 0.2439*M + 1.2045*S;
} return I;
} Vector<double> computeMeans(Mat m)
{
double sum[] = { };
int pixes = m.cols * m.rows;
Vector<double> means;
means.resize();
Mat_<Vec3f> I = m; for(int i=;i<I.rows;++i)
for(int j=;j<I.cols;++j)
{
for(int k = ;k < ;k++)
{
sum[k] += I(i,j)[k];
}
} for(int i = ;i < ;i++)
{
means[i] = sum[i] / pixes;
} return means;
} Vector<double> computeVariances(Mat m, Vector<double> means)
{
double sum[] = { };
int pixes = m.cols * m.rows;
Mat_<Vec3f> I = m;
Vector<double> variances;
variances.resize(); for(int i=;i<I.rows;++i)
for(int j=;j<I.cols;++j)
{
for(int chanel = ;chanel < ;chanel++)
{
sum[chanel] += abs(I(i,j)[chanel] - means[chanel]);
}
} for(int i = ;i < ;i++)
{
variances[i] = sqrt(sum[i] / pixes);
} return variances;
} void computeResult()
{
Mat_<Vec3f> I = resultImg;
double dataTemp[] = { }; for(int chanel =;chanel < ;chanel++)
{
dataTemp[chanel] = targetVariances[chanel] / srcVariances[chanel];
} for(int i=;i<I.rows;++i)
for(int j=;j<I.cols;++j)
{
for(int chanel = ;chanel < ;chanel++)
{
I(i,j)[chanel] = dataTemp[chanel] * (I(i,j)[chanel]-srcMeans[chanel]) + targetMeans[chanel];
}
}
resultImg = LabToRGB(resultImg);
}
}; int main()
{
Mat src = imread("11.jpg");
namedWindow("src");
imshow("src", src);
Mat target = imread("12.jpg");
namedWindow("target");
imshow("target", target);
ColorTransfer clt(src,target);
namedWindow("result");
imshow("result", clt.resultImg);
Mat saveImg;
clt.resultImg.convertTo(saveImg,CV_8U, 255.0, /255.0);//imwrite函数只支持8bit和16bit,前面将图像转为了float,保存前要转换
imwrite("result.jpg",saveImg); waitKey();
return ;
}