• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of the copyright holders may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 #include "precomp.hpp"
43 #include "opencv2/photo.hpp"
44 #include "math.h"
45 #include <vector>
46 #include <limits>
47 
48 using namespace std;
49 using namespace cv;
50 
51 class Decolor
52 {
53     private:
54         Mat kernelx;
55         Mat kernely;
56         int order;
57 
58     public:
59         float sigma;
60         void init();
61         vector<double> product(vector < vector<int> > &comb, vector <double> &initRGB);
62         double energyCalcu(vector <double> &Cg, vector < vector <double> > &polyGrad, vector <double> &wei);
63         void singleChannelGradx(const Mat &img, Mat& dest);
64         void singleChannelGrady(const Mat &img, Mat& dest);
65         void gradvector(const Mat &img, vector <double> &grad);
66         void colorGrad(Mat img, vector <double> &Cg);
67         void add_vector(vector < vector <int> > &comb, int &idx, int r,int g,int b);
68         void add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad, int &idx1);
69         void weak_order(Mat img, vector <double> &alf);
70         void grad_system(Mat img, vector < vector < double > > &polyGrad,
71                 vector < double > &Cg, vector < vector <int> >& comb);
72         void wei_update_matrix(vector < vector <double> > &poly, vector <double> &Cg, Mat &X);
73         void wei_inti(vector < vector <int> > &comb, vector <double> &wei);
74         void grayImContruct(vector <double> &wei, Mat img, Mat &Gray);
75 };
76 
77 int round_num(double a);
78 
round_num(double a)79 int round_num(double a)
80 {
81     return int(a + 0.5);
82 }
83 
energyCalcu(vector<double> & Cg,vector<vector<double>> & polyGrad,vector<double> & wei)84 double Decolor::energyCalcu(vector <double> &Cg, vector < vector <double> > &polyGrad, vector <double> &wei)
85 {
86     vector <double> energy;
87     vector <double> temp;
88     vector <double> temp1;
89 
90     double val = 0.0;
91     for(unsigned int i=0;i< polyGrad[0].size();i++)
92     {
93         val = 0.0;
94         for(unsigned int j =0;j<polyGrad.size();j++)
95             val = val + (polyGrad[j][i] * wei[j]);
96         temp.push_back(val - Cg[i]);
97         temp1.push_back(val + Cg[i]);
98     }
99 
100     for(unsigned int i=0;i<polyGrad[0].size();i++)
101         energy.push_back(-1.0*log(exp(-1.0*pow(temp[i],2)/sigma) + exp(-1.0*pow(temp1[i],2)/sigma)));
102 
103     double sum = 0.0;
104     for(unsigned int i=0;i<polyGrad[0].size();i++)
105         sum +=energy[i];
106 
107     return (sum/polyGrad[0].size());
108 
109 }
110 
init()111 void Decolor::init()
112 {
113     kernelx = Mat(1,2, CV_32FC1);
114     kernely = Mat(2,1, CV_32FC1);
115     kernelx.at<float>(0,0)=1.0;
116     kernelx.at<float>(0,1)=-1.0;
117     kernely.at<float>(0,0)=1.0;
118     kernely.at<float>(1,0)=-1.0;
119     order = 2;
120     sigma = 0.02f;
121 }
122 
product(vector<vector<int>> & comb,vector<double> & initRGB)123 vector<double> Decolor::product(vector < vector<int> > &comb, vector <double> &initRGB)
124 {
125     vector <double> res;
126     double dp;
127     for (unsigned int i=0;i<comb.size();i++)
128     {
129         dp = 0.0;
130         for(int j=0;j<3;j++)
131             dp = dp + (comb[i][j] * initRGB[j]);
132         res.push_back(dp);
133     }
134     return res;
135 }
136 
singleChannelGradx(const Mat & img,Mat & dest)137 void Decolor::singleChannelGradx(const Mat &img, Mat& dest)
138 {
139     int w=img.size().width;
140     int h=img.size().height;
141     Point anchor(kernelx.cols - kernelx.cols/2 - 1, kernelx.rows - kernelx.rows/2 - 1);
142     filter2D(img, dest, -1, kernelx, anchor, 0.0, BORDER_CONSTANT);
143     for(int i=0;i<h;i++)
144         dest.at<float>(i,w-1)=0.0;
145 }
146 
singleChannelGrady(const Mat & img,Mat & dest)147 void Decolor::singleChannelGrady(const Mat &img, Mat& dest)
148 {
149     int w=img.size().width;
150     int h=img.size().height;
151     Point anchor(kernely.cols - kernely.cols/2 - 1, kernely.rows - kernely.rows/2 - 1);
152     filter2D(img, dest, -1, kernely, anchor, 0.0, BORDER_CONSTANT);
153     for(int j=0;j<w;j++)
154         dest.at<float>(h-1,j)=0.0;
155 }
156 
gradvector(const Mat & img,vector<double> & grad)157 void Decolor::gradvector(const Mat &img, vector <double> &grad)
158 {
159     Mat dest= Mat(img.size().height,img.size().width, CV_32FC1);
160     Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1);
161     singleChannelGradx(img,dest);
162     singleChannelGrady(img,dest1);
163 
164     Mat d_trans=dest.t();
165     Mat d1_trans=dest1.t();
166 
167     int height = d_trans.size().height;
168     int width = d_trans.size().width;
169 
170     for(int i=0;i<height;i++)
171         for(int j=0;j<width;j++)
172             grad.push_back(d_trans.at<float>(i,j));
173 
174     for(int i=0;i<height;i++)
175         for(int j=0;j<width;j++)
176             grad.push_back(d1_trans.at<float>(i,j));
177     dest.release();
178     dest1.release();
179 }
180 
colorGrad(Mat img,vector<double> & Cg)181 void Decolor::colorGrad(Mat img, vector <double> &Cg)
182 {
183 
184     Mat lab = Mat(img.size(),CV_32FC3);
185 
186     cvtColor(img,lab,COLOR_BGR2Lab);
187 
188     vector <Mat> lab_channel;
189     split(lab,lab_channel);
190 
191     vector <double> ImL;
192     vector <double> Ima;
193     vector <double> Imb;
194 
195     gradvector(lab_channel[0],ImL);
196     gradvector(lab_channel[1],Ima);
197     gradvector(lab_channel[2],Imb);
198 
199     double res =0.0;
200     for(unsigned int i=0;i<ImL.size();i++)
201     {
202         res=sqrt(pow(ImL[i],2) + pow(Ima[i],2) + pow(Imb[i],2))/100;
203         Cg.push_back(res);
204     }
205 
206     ImL.clear();
207     Ima.clear();
208     Imb.clear();
209 }
210 
add_vector(vector<vector<int>> & comb,int & idx,int r,int g,int b)211 void Decolor::add_vector(vector < vector <int> > &comb, int &idx, int r,int g,int b)
212 {
213     comb.push_back( vector <int>() );
214     comb.at(idx).push_back( r );
215     comb.at(idx).push_back( g );
216     comb.at(idx).push_back( b );
217     idx++;
218 }
219 
add_to_vector_poly(vector<vector<double>> & polyGrad,vector<double> & curGrad,int & idx1)220 void Decolor::add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad, int &idx1)
221 {
222     polyGrad.push_back( vector <double>() );
223     for(unsigned int i=0;i<curGrad.size();i++)
224         polyGrad.at(idx1).push_back(curGrad[i]);
225     idx1++;
226 }
227 
weak_order(Mat img,vector<double> & alf)228 void Decolor::weak_order(Mat img, vector <double> &alf)
229 {
230     int h = img.size().height;
231     int w = img.size().width;
232     double sizefactor;
233     if((h + w) > 800)
234     {
235         sizefactor = (double)800/(h+w);
236         resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)));
237     }
238 
239     Mat curIm = Mat(img.size(),CV_32FC1);
240     vector <Mat> rgb_channel;
241     split(img,rgb_channel);
242 
243     vector <double> Rg, Gg, Bg;
244     vector <double> t1, t2, t3;
245     vector <double> tmp1, tmp2, tmp3;
246 
247     gradvector(rgb_channel[2],Rg);
248     gradvector(rgb_channel[1],Gg);
249     gradvector(rgb_channel[0],Bg);
250 
251     double level = .05;
252 
253     for(unsigned int i=0;i<Rg.size();i++)
254     {
255         if(Rg[i] > level)
256             t1.push_back(1.0);
257         else
258             t1.push_back(0.0);
259 
260         if(Gg[i] > level)
261             t2.push_back(1.0);
262         else
263             t2.push_back(0.0);
264 
265         if(Bg[i] > level)
266             t3.push_back(1.0);
267         else
268             t3.push_back(0.0);
269 
270         if(Rg[i] < -1.0*level)
271             tmp1.push_back(1.0);
272         else
273             tmp1.push_back(0.0);
274 
275         if(Gg[i] < -1.0*level)
276             tmp2.push_back(1.0);
277         else
278             tmp2.push_back(0.0);
279 
280         if(Bg[i] < -1.0*level)
281             tmp3.push_back(1.0);
282         else
283             tmp3.push_back(0.0);
284     }
285     for(unsigned int i =0 ;i < Rg.size();i++)
286         alf.push_back(t1[i] * t2[i] * t3[i]);
287 
288     for(unsigned int i =0 ;i < Rg.size();i++)
289         alf[i] -= tmp1[i] * tmp2[i] * tmp3[i];
290 
291     double sum =0.0;
292     for(unsigned int i=0;i<alf.size();i++)
293         sum += abs(alf[i]);
294 
295     sum = (double)100*sum/alf.size();
296 
297     Rg.clear(); Gg.clear(); Bg.clear();
298     t1.clear(); t2.clear(); t3.clear();
299     tmp1.clear(); tmp2.clear(); tmp3.clear();
300 }
301 
grad_system(Mat img,vector<vector<double>> & polyGrad,vector<double> & Cg,vector<vector<int>> & comb)302 void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
303         vector < double > &Cg, vector < vector <int> >& comb)
304 {
305     int h = img.size().height;
306     int w = img.size().width;
307 
308     double sizefactor;
309     if((h + w) > 800)
310     {
311         sizefactor = (double)800/(h+w);
312         resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)));
313     }
314 
315     h = img.size().height;
316     w = img.size().width;
317     colorGrad(img,Cg);
318 
319     Mat curIm = Mat(img.size(),CV_32FC1);
320     vector <Mat> rgb_channel;
321     split(img,rgb_channel);
322 
323     int idx = 0, idx1 = 0;
324     for(int r=0 ;r <=order; r++)
325         for(int g=0; g<=order;g++)
326             for(int b =0; b <=order;b++)
327             {
328                 if((r+g+b)<=order && (r+g+b) > 0)
329                 {
330                     add_vector(comb,idx,r,g,b);
331                     for(int i = 0;i<h;i++)
332                         for(int j=0;j<w;j++)
333                             curIm.at<float>(i,j)=
334                                 pow(rgb_channel[2].at<float>(i,j),r)*pow(rgb_channel[1].at<float>(i,j),g)*
335                                 pow(rgb_channel[0].at<float>(i,j),b);
336                     vector <double> curGrad;
337                     gradvector(curIm,curGrad);
338                     add_to_vector_poly(polyGrad,curGrad,idx1);
339                 }
340             }
341 }
342 
wei_update_matrix(vector<vector<double>> & poly,vector<double> & Cg,Mat & X)343 void Decolor::wei_update_matrix(vector < vector <double> > &poly, vector <double> &Cg, Mat &X)
344 {
345     int size = static_cast<int>(poly.size()), size0 = static_cast<int>(poly[0].size());
346     Mat P = Mat(size, size0, CV_32FC1);
347     Mat A = Mat(size, size, CV_32FC1);
348 
349     for (int i = 0; i < size; i++)
350         for (int j = 0; j < size0;j++)
351             P.at<float>(i,j) = (float) poly[i][j];
352 
353     Mat P_trans = P.t();
354     Mat B = Mat(size, size0, CV_32FC1);
355     for(int i =0;i < size;i++)
356     {
357         for(int j = 0, end = (int)Cg.size(); j < end;j++)
358             B.at<float>(i,j) = (float) (poly[i][j] * Cg[j]);
359     }
360 
361     A = P*P_trans;
362     solve(A, B, X, DECOMP_NORMAL);
363 
364 }
365 
wei_inti(vector<vector<int>> & comb,vector<double> & wei)366 void Decolor::wei_inti(vector < vector <int> > &comb, vector <double> &wei)
367 {
368     vector <double> initRGB;
369 
370     initRGB.push_back( .33 );
371     initRGB.push_back( .33 );
372     initRGB.push_back( .33 );
373     wei = product(comb,initRGB);
374 
375     vector <int> sum;
376 
377     for(unsigned int i=0;i<comb.size();i++)
378         sum.push_back(comb[i][0] + comb[i][1] + comb[i][2]);
379 
380     for(unsigned int i=0;i<sum.size();i++)
381     {
382         if(sum[i] == 1)
383             wei[i] = wei[i] * double(1);
384         else
385             wei[i] = wei[i] * double(0);
386     }
387 
388     initRGB.clear();
389     sum.clear();
390 
391 }
392 
grayImContruct(vector<double> & wei,Mat img,Mat & Gray)393 void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
394 {
395     int h=img.size().height;
396     int w=img.size().width;
397 
398     vector <Mat> rgb_channel;
399     split(img,rgb_channel);
400 
401     int kk =0;
402 
403     for(int r =0;r<=order;r++)
404         for(int g=0;g<=order;g++)
405             for(int b=0;b<=order;b++)
406                 if((r + g + b) <=order && (r+g+b) > 0)
407                 {
408                     for(int i = 0;i<h;i++)
409                         for(int j=0;j<w;j++)
410                             Gray.at<float>(i,j)=Gray.at<float>(i,j) +
411                                 (float) wei[kk]*pow(rgb_channel[2].at<float>(i,j),r)*pow(rgb_channel[1].at<float>(i,j),g)*
412                                 pow(rgb_channel[0].at<float>(i,j),b);
413 
414                     kk=kk+1;
415                 }
416 
417     float minval = FLT_MAX;
418     float maxval = -FLT_MAX;
419 
420     for(int i=0;i<h;i++)
421         for(int j =0;j<w;j++)
422        {
423             if(Gray.at<float>(i,j) < minval)
424                 minval = Gray.at<float>(i,j);
425 
426             if(Gray.at<float>(i,j) > maxval)
427                 maxval = Gray.at<float>(i,j);
428         }
429 
430     Gray -= minval;
431     Gray /= maxval - minval;
432 }
433