diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index ce31e0cd26..b20bba0893 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -42,7 +42,7 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "math.h" +#include #include #include #include "contrast_preserve.hpp" @@ -64,33 +64,28 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) CV_Assert(!I.empty() && (I.channels()==3)); // Parameter Setting - int maxIter = 15; + const int maxIter = 15; + const double tol = .0001; int iterCount = 0; - double tol = .0001; double E = 0; double pre_E = std::numeric_limits::infinity(); - Decolor obj; - Mat img; - - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + I.convertTo(img, CV_32FC3, 1.0/255.0); // Initialization - obj.init(); + Decolor obj; vector Cg; vector < vector > polyGrad; vector comb; - vector alf; obj.grad_system(img,polyGrad,Cg,comb); obj.weak_order(img,alf); // Solver - Mat Mt = Mat((int)polyGrad.size(),(int)polyGrad[0].size(), CV_32FC1); + Mat Mt = Mat(int(polyGrad.size()),int(polyGrad[0].size()), CV_32FC1); obj.wei_update_matrix(polyGrad,Cg,Mt); vector wei; @@ -98,85 +93,64 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) //////////////////////////////// main loop starting //////////////////////////////////////// + vector G_pos(alf.size()); + vector G_neg(alf.size()); + vector EXPsum(G_pos.size()); + vector EXPterm(G_pos.size()); + vector temp(polyGrad[0].size()); + vector temp1(polyGrad[0].size()); + vector temp2(EXPsum.size()); + vector wei1(polyGrad.size()); + while(sqrt(pow(E-pre_E,2)) > tol) { iterCount +=1; pre_E = E; - vector G_pos(alf.size()); - vector G_neg(alf.size()); - - vector temp(polyGrad[0].size()); - vector temp1(polyGrad[0].size()); - - double val = 0.0; - for(unsigned int i=0;i< polyGrad[0].size();i++) + for(size_t i=0; i EXPsum(G_pos.size()); - vector EXPterm(G_pos.size()); - - for(unsigned int i = 0;i temp2(EXPsum.size()); - - for(unsigned int i=0;i wei1(polyGrad.size()); - - for(unsigned int i=0;i< polyGrad.size();i++) + for(int i=0; i(i,j) * EXPterm[j]); } wei1[i] = val1; } - for(unsigned int i =0;i maxIter) break; - - G_pos.clear(); - G_neg.clear(); - temp.clear(); - temp1.clear(); - EXPsum.clear(); - EXPterm.clear(); - temp2.clear(); - wei1.clear(); } Mat Gray = Mat::zeros(img.size(),CV_32FC1); @@ -186,9 +160,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) /////////////////////////////////// Contrast Boosting ///////////////////////////////// - Mat lab = Mat(img.size(),CV_8UC3); - Mat color = Mat(img.size(),CV_8UC3); - + Mat lab; cvtColor(I,lab,COLOR_BGR2Lab); vector lab_channel; diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 2504cee4fe..ec8274e883 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -41,9 +41,8 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "math.h" +#include #include -#include using namespace std; using namespace cv; @@ -57,41 +56,34 @@ class Decolor public: float sigma; - void init(); - vector product(vector &comb, const double initRGB[3]); - double energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei); - void singleChannelGradx(const Mat &img, Mat& dest); - void singleChannelGrady(const Mat &img, Mat& dest); - void gradvector(const Mat &img, vector &grad); - void colorGrad(Mat img, vector &Cg); - void add_vector(vector &comb, int &idx, int r,int g,int b); - void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad, int &idx1); - void weak_order(Mat img, vector &alf); - void grad_system(Mat img, vector < vector < double > > &polyGrad, - vector < double > &Cg, vector & comb); - void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); - void wei_inti(vector &comb, vector &wei); - void grayImContruct(vector &wei, Mat img, Mat &Gray); -}; - -int round_num(double a); -int round_num(double a) -{ - return int(a + 0.5); -} + Decolor(); + static vector product(const vector &comb, const double initRGB[3]); + double energyCalcu(const vector &Cg, const vector < vector > &polyGrad, const vector &wei) const; + void singleChannelGradx(const Mat &img, Mat& dest) const; + void singleChannelGrady(const Mat &img, Mat& dest) const; + void gradvector(const Mat &img, vector &grad) const; + void colorGrad(const Mat &img, vector &Cg) const; + static void add_vector(vector &comb, int &idx, int r,int g,int b); + static void add_to_vector_poly(vector < vector > &polyGrad, const vector &curGrad, int &idx1); + void weak_order(const Mat &img, vector &alf) const; + void grad_system(const Mat &img, vector < vector < double > > &polyGrad, + vector < double > &Cg, vector & comb) const; + static void wei_update_matrix(const vector < vector > &poly, const vector &Cg, Mat &X); + static void wei_inti(const vector &comb, vector &wei); + void grayImContruct(vector &wei, const Mat &img, Mat &Gray) const; +}; -double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) +double Decolor::energyCalcu(const vector &Cg, const vector < vector > &polyGrad, const vector &wei) const { const size_t size = polyGrad[0].size(); vector energy(size); vector temp(size); vector temp1(size); - double val = 0.0; for(size_t i=0;i< polyGrad[0].size();i++) { - val = 0.0; + double val = 0.0; for(size_t j =0;j &Cg, vector < vector > &pol } -void Decolor::init() +Decolor::Decolor() { kernelx = Mat(1,2, CV_32FC1); kernely = Mat(2,1, CV_32FC1); @@ -121,13 +113,12 @@ void Decolor::init() sigma = 0.02f; } -vector Decolor::product(vector &comb, const double initRGB[3]) +vector Decolor::product(const vector &comb, const double initRGB[3]) { vector res(comb.size()); - double dp; for (size_t i=0;i Decolor::product(vector &comb, const double initRGB[3]) return res; } -void Decolor::singleChannelGradx(const Mat &img, Mat& dest) +void Decolor::singleChannelGradx(const Mat &img, Mat& dest) const { - int w=img.size().width; - int h=img.size().height; - Point anchor(kernelx.cols - kernelx.cols/2 - 1, kernelx.rows - kernelx.rows/2 - 1); + const int w = img.size().width; + const Point anchor(kernelx.cols - kernelx.cols/2 - 1, kernelx.rows - kernelx.rows/2 - 1); filter2D(img, dest, -1, kernelx, anchor, 0.0, BORDER_CONSTANT); - for(int i=0;i(i,w-1)=0.0; + dest.col(w - 1) = 0.0; } -void Decolor::singleChannelGrady(const Mat &img, Mat& dest) +void Decolor::singleChannelGrady(const Mat &img, Mat& dest) const { - int w=img.size().width; - int h=img.size().height; - Point anchor(kernely.cols - kernely.cols/2 - 1, kernely.rows - kernely.rows/2 - 1); + const int h = img.size().height; + const Point anchor(kernely.cols - kernely.cols/2 - 1, kernely.rows - kernely.rows/2 - 1); filter2D(img, dest, -1, kernely, anchor, 0.0, BORDER_CONSTANT); - for(int j=0;j(h-1,j)=0.0; + dest.row(h - 1) = 0.0; } -void Decolor::gradvector(const Mat &img, vector &grad) +void Decolor::gradvector(const Mat &img, vector &grad) const { Mat dest; Mat dest1; @@ -165,8 +152,8 @@ void Decolor::gradvector(const Mat &img, vector &grad) Mat d_trans=dest.t(); Mat d1_trans=dest1.t(); - int height = d_trans.size().height; - int width = d_trans.size().width; + const int height = d_trans.size().height; + const int width = d_trans.size().width; grad.resize(width * height * 2); @@ -180,9 +167,8 @@ void Decolor::gradvector(const Mat &img, vector &grad) grad[offset + i * height + j] = d1_trans.at(i, j); } -void Decolor::colorGrad(Mat img, vector &Cg) +void Decolor::colorGrad(const Mat &img, vector &Cg) const { - Mat lab; cvtColor(img,lab,COLOR_BGR2Lab); @@ -199,10 +185,9 @@ void Decolor::colorGrad(Mat img, vector &Cg) gradvector(lab_channel[2],Imb); Cg.resize(ImL.size()); - double res =0.0; for(size_t i=0;i &comb, int &idx, int r,int g,int b) idx++; } -void Decolor::add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad, int &idx1) +void Decolor::add_to_vector_poly(vector < vector > &polyGrad, const vector &curGrad, int &idx1) { polyGrad.push_back(curGrad); idx1++; } -void Decolor::weak_order(Mat img, vector &alf) +void Decolor::weak_order(const Mat &img, vector &alf) const { - int h = img.size().height; - int w = img.size().width; - double sizefactor; + const int h = img.size().height; + const int w = img.size().width; if((h + w) > 800) { - sizefactor = (double)800/(h+w); - resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); + const double sizefactor = double(800)/(h+w); + resize(img, img, Size(cvRound(h*sizefactor), cvRound(w*sizefactor))); } Mat curIm = Mat(img.size(),CV_32FC1); @@ -242,39 +226,16 @@ void Decolor::weak_order(Mat img, vector &alf) vector t1(Rg.size()), t2(Rg.size()), t3(Rg.size()); vector tmp1(Rg.size()), tmp2(Rg.size()), tmp3(Rg.size()); - double level = .05; + const double level = .05; - for(unsigned int i=0;i level) - t1[i] = 1.0; - else - t1[i] = 0.0; - - if(Gg[i] > level) - t2[i] = 1.0; - else - t2[i] = 0.0; - - if(Bg[i] > level) - t3[i] = 1.0; - else - t3[i] = 0.0; - - if(Rg[i] < -1.0*level) - tmp1[i] = 1.0; - else - tmp1[i] = 0.0; - - if(Gg[i] < -1.0*level) - tmp2[i] = 1.0; - else - tmp2[i] = 0.0; - - if(Bg[i] < -1.0*level) - tmp3[i] = 1.0; - else - tmp3[i] = 0.0; + t1[i] = (Rg[i] > level) ? 1.0 : 0.0; + t2[i] = (Gg[i] > level) ? 1.0 : 0.0; + t3[i] = (Bg[i] > level) ? 1.0 : 0.0; + tmp1[i] = (Rg[i] < -1.0*level) ? 1.0 : 0.0; + tmp2[i] = (Gg[i] < -1.0*level) ? 1.0 : 0.0; + tmp3[i] = (Bg[i] < -1.0*level) ? 1.0 : 0.0; } alf.resize(Rg.size()); @@ -283,29 +244,18 @@ void Decolor::weak_order(Mat img, vector &alf) for(size_t i =0 ;i < Rg.size();i++) alf[i] -= tmp1[i] * tmp2[i] * tmp3[i]; - - double sum =0.0; - for(unsigned int i=0;i > &polyGrad, - vector < double > &Cg, vector & comb) +void Decolor::grad_system(const Mat &img, vector < vector < double > > &polyGrad, + vector < double > &Cg, vector & comb) const { int h = img.size().height; int w = img.size().width; - double sizefactor; if((h + w) > 800) { - sizefactor = (double)800/(h+w); - resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); + const double sizefactor = double(800)/(h+w); + resize(img, img, Size(cvRound(h*sizefactor), cvRound(w*sizefactor))); } h = img.size().height; @@ -336,30 +286,30 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, } } -void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) +void Decolor::wei_update_matrix(const vector < vector > &poly, const vector &Cg, Mat &X) { - int size = static_cast(poly.size()), size0 = static_cast(poly[0].size()); + const int size = static_cast(poly.size()); + const int size0 = static_cast(poly[0].size()); Mat P = Mat(size, size0, CV_32FC1); - Mat A = Mat(size, size, CV_32FC1); for (int i = 0; i < size; i++) for (int j = 0; j < size0;j++) - P.at(i,j) = (float) poly[i][j]; + P.at(i,j) = static_cast(poly[i][j]); - Mat P_trans = P.t(); + const Mat P_trans = P.t(); Mat B = Mat(size, size0, CV_32FC1); for(int i =0;i < size;i++) { - for(int j = 0, end = (int)Cg.size(); j < end;j++) - B.at(i,j) = (float) (poly[i][j] * Cg[j]); + for(int j = 0, end = int(Cg.size()); j < end;j++) + B.at(i,j) = static_cast(poly[i][j] * Cg[j]); } - A = P*P_trans; + Mat A = P*P_trans; solve(A, B, X, DECOMP_NORMAL); } -void Decolor::wei_inti(vector &comb, vector &wei) +void Decolor::wei_inti(const vector &comb, vector &wei) { double initRGB[3] = { .33, .33, .33 }; @@ -367,10 +317,10 @@ void Decolor::wei_inti(vector &comb, vector &wei) vector sum(comb.size()); - for(unsigned int i=0;i &comb, vector &wei) } -void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) +void Decolor::grayImContruct(vector &wei, const Mat &img, Mat &Gray) const { - int h=img.size().height; - int w=img.size().width; + const int h = img.size().height; + const int w = img.size().width; vector rgb_channel; split(img,rgb_channel); @@ -400,25 +350,15 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*pow(rgb_channel[2].at(i,j),r)*pow(rgb_channel[1].at(i,j),g)* + static_cast(wei[kk])*pow(rgb_channel[2].at(i,j),r)*pow(rgb_channel[1].at(i,j),g)* pow(rgb_channel[0].at(i,j),b); kk=kk+1; } - float minval = FLT_MAX; - float maxval = -FLT_MAX; - - for(int i=0;i(i,j) < minval) - minval = Gray.at(i,j); - - if(Gray.at(i,j) > maxval) - maxval = Gray.at(i,j); - } + double minval, maxval; + minMaxLoc(Gray, &minval, &maxval); Gray -= minval; Gray /= maxval - minval; -} \ No newline at end of file +} diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index a6d13c3e94..b40bc1fd04 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -45,24 +45,24 @@ namespace opencv_test { namespace { TEST(Photo_Decolor, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; - string original_path = folder + "color_image_1.png"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; + string original_path = folder + "color_image_1.png"; - Mat original = imread(original_path, IMREAD_COLOR); + Mat original = imread(original_path, IMREAD_COLOR); - ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; - ASSERT_EQ(3, original.channels()) << "Load color input image " << original_path; + ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; + ASSERT_EQ(3, original.channels()) << "Load color input image " << original_path; - Mat grayscale, color_boost; - decolor(original, grayscale, color_boost); + Mat grayscale, color_boost; + decolor(original, grayscale, color_boost); - Mat reference_grayscale = imread(folder + "grayscale_reference.png", 0 /* == grayscale image*/); - double gray_psnr = cvtest::PSNR(reference_grayscale, grayscale); - EXPECT_GT(gray_psnr, 60.0); + Mat reference_grayscale = imread(folder + "grayscale_reference.png", 0 /* == grayscale image*/); + double gray_psnr = cvtest::PSNR(reference_grayscale, grayscale); + EXPECT_GT(gray_psnr, 60.0); - Mat reference_boost = imread(folder + "boost_reference.png"); - double boost_psnr = cvtest::PSNR(reference_boost, color_boost); - EXPECT_GT(boost_psnr, 60.0); + Mat reference_boost = imread(folder + "boost_reference.png"); + double boost_psnr = cvtest::PSNR(reference_boost, color_boost); + EXPECT_GT(boost_psnr, 60.0); } }} // namespace