Home | History | Annotate | Download | only in src
      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 
     79 int round_num(double a)
     80 {
     81     return int(a + 0.5);
     82 }
     83 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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