Color Transfer between Images code实现

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

基本思路是:

1.给定srcImg和targetImg

2.将RGB空间转为Lab空间

3.根据论文中公式:

计算每一个像素点

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

效果图:

  

  

见代码:

  1 #include <opencv2/opencv.hpp>  
  2 #include <opencv2/core/core.hpp>  
  3 #include <opencv2/imgproc/imgproc.hpp>
  4 #include <math.h>
  5 using namespace std;
  6 using namespace cv;
  7 
  8 class ColorTransfer
  9 {
 10 public:
 11     Mat resultImg;
 12 
 13     ColorTransfer(Mat src, Mat target)
 14     {
 15         src.convertTo(srcImg_32F, CV_32FC3,1.0f/255.f);//这里切记要类型转换下
 16         target.convertTo(targetImg_32F, CV_32FC3, 1.0f/255.0f);
 17         resultImg = srcImg_32F;  //将结果先初始化为源图像
 18         
 19         srcImg_Lab = RGBToLab(srcImg_32F);
 20         targetImg_Lab = RGBToLab(targetImg_32F);
 21         srcMeans = computeMeans(srcImg_Lab);
 22         targetMeans = computeMeans(targetImg_Lab);
 23         srcVariances = computeVariances(srcImg_Lab, srcMeans);
 24         targetVariances = computeVariances(targetImg_Lab, targetMeans);
 25         computeResult();
 26     }
 27 
 28 private:
 29     //读入的RGB图像
 30     Mat srcImg_32F;
 31     Mat targetImg_32F;
 32     //转换后的Lab空间图像
 33     Mat srcImg_Lab;
 34     Mat targetImg_Lab;
 35     //计算得到的均值和方差
 36     Vector<double> srcMeans;
 37     Vector<double> targetMeans;
 38     Vector<double> srcVariances;
 39     Vector<double> targetVariances;
 40 
 41     //RGB转换到Lab空间
 42     Mat RGBToLab(Mat m)
 43     {
 44         Mat_<Vec3f> I = m;
 45         for(int i=0;i<I.rows;++i)
 46         {
 47             for(int j=0;j<I.cols;++j)
 48             {
 49                 double L = 0.3811*I(i,j)[0] + 0.5783*I(i,j)[1] + 0.0402*I(i,j)[2];
 50                 double M = 0.1967*I(i,j)[0] + 0.7244*I(i,j)[1] + 0.0782*I(i,j)[2];
 51                 double S = 0.0241*I(i,j)[0] + 0.1288*I(i,j)[1] + 0.8444*I(i,j)[2];
 52                 if(L == 0) L = 1;
 53                 if(M == 0) M = 1;
 54                 if(S == 0) S = 1;
 55                 L = log(L);
 56                 M = log(M);
 57                 S = log(S);
 58             
 59                 I(i,j)[0] = (L+M+S) / sqrt(3.0);
 60                 I(i,j)[1] = (L+M-2*S) / sqrt(6.0);
 61                 I(i,j)[2] = (L-M) / sqrt(2.0);
 62             }
 63         }
 64 
 65         return I;
 66     }
 67 
 68     //Lab转换到RGB空间
 69     Mat LabToRGB(Mat m)
 70     {
 71         Mat_<Vec3f> I = m;
 72         for(int i=0;i<I.rows;++i)
 73         for(int j=0;j<I.cols;++j)
 74         {
 75             double L = I(i,j)[0]/sqrt(3.0) + I(i,j)[1]/sqrt(6.0) + I(i,j)[2]/sqrt(2.0);
 76             double M = I(i,j)[0]/sqrt(3.0) + I(i,j)[1]/sqrt(6.0) - I(i,j)[2]/sqrt(2.0);
 77             double S = I(i,j)[0]/sqrt(3.0) - 2*I(i,j)[1]/sqrt(6.0);
 78 
 79             L = exp(L);
 80             M = exp(M);
 81             S = exp(S);
 82             
 83             I(i,j)[0] = 4.4679*L - 3.5873*M + 0.1193*S;
 84             I(i,j)[1] = -1.2186*L + 2.3809*M - 0.1624*S;
 85             I(i,j)[2] = 0.0497*L - 0.2439*M + 1.2045*S;
 86         }
 87 
 88         return I;
 89     }
 90 
 91     Vector<double> computeMeans(Mat m)
 92     {
 93         double sum[3] = { 0 };
 94         int pixes = m.cols * m.rows;
 95         Vector<double> means;
 96         means.resize(3);
 97         Mat_<Vec3f> I = m;
 98         
 99         for(int i=0;i<I.rows;++i)
100         for(int j=0;j<I.cols;++j)
101         {
102             for(int k = 0;k < 3;k++)
103             {
104                 sum[k] += I(i,j)[k];
105             }
106         }
107 
108         for(int i = 0;i < 3;i++)
109         {
110             means[i] = sum[i] / pixes;
111         }
112 
113         return means;
114     }
115 
116     Vector<double> computeVariances(Mat m, Vector<double> means)
117     {
118         double sum[3] = { 0 };
119         int pixes = m.cols * m.rows;
120         Mat_<Vec3f> I = m;
121         Vector<double> variances;
122         variances.resize(3);
123 
124         for(int i=0;i<I.rows;++i)
125         for(int j=0;j<I.cols;++j)
126         {
127             for(int chanel = 0;chanel < 3;chanel++)
128             {
129                 sum[chanel] += abs(I(i,j)[chanel] - means[chanel]);
130             }
131         }
132 
133         for(int i = 0;i < 3;i++)
134         {
135             variances[i] = sqrt(sum[i] / pixes);
136         }
137 
138         return variances;
139     }
140 
141     void computeResult()
142     {
143         Mat_<Vec3f> I = resultImg;
144         double dataTemp[3] = { 0 };
145         
146         for(int chanel =0;chanel < 3;chanel++)
147         {
148             dataTemp[chanel] = targetVariances[chanel] / srcVariances[chanel];
149         }
150         
151         for(int i=0;i<I.rows;++i)
152         for(int j=0;j<I.cols;++j)
153         {
154             for(int chanel = 0;chanel < 3;chanel++)
155             {
156                 I(i,j)[chanel] = dataTemp[chanel] * (I(i,j)[chanel]-srcMeans[chanel]) + targetMeans[chanel];
157             }
158         }
159         resultImg = LabToRGB(resultImg);
160     }
161 };
162 
163 int main()
164 {
165     Mat src = imread("11.jpg");
166     namedWindow("src");  
167     imshow("src", src); 
168     Mat target = imread("12.jpg");
169     namedWindow("target");
170     imshow("target", target);
171     ColorTransfer clt(src,target);
172     namedWindow("result");
173     imshow("result", clt.resultImg);
174     Mat saveImg;
175     clt.resultImg.convertTo(saveImg,CV_8U, 255.0, 1/255.0);//imwrite函数只支持8bit和16bit,前面将图像转为了float,保存前要转换
176     imwrite("result.jpg",saveImg);
177 
178     waitKey(0);
179     return 0;
180 }
原文地址:https://www.cnblogs.com/xlturing/p/3463813.html