From 95db69f6b95d5faedf4e4f2116daa1202df28c6e Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 15 Jun 2013 16:19:31 +0530 Subject: [PATCH 01/27] added new files --- modules/photo/include/opencv2/photo.hpp | 2 + modules/photo/src/contrast_preserve.cpp | 76 +++++++++++++++++++++++++ modules/photo/src/contrast_preserve.hpp | 31 ++++++++++ 3 files changed, 109 insertions(+) create mode 100644 modules/photo/src/contrast_preserve.cpp create mode 100644 modules/photo/src/contrast_preserve.hpp diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index beec929235..e656b93e8a 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -288,6 +288,8 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); +CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); + } // cv #endif diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp new file mode 100644 index 0000000000..271afb5e7e --- /dev/null +++ b/modules/photo/src/contrast_preserve.cpp @@ -0,0 +1,76 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "math.h" +#include +#include +#include + +#include "contrast_preserve.hpp" + +using namespace std; +using namespace cv; +int rounding(double); + +int rounding(double a) +{ + return int(a + 0.5); +} + +void cv::decolor(InputArray _src, OutputArray _gray, OutputArray _boost) +{ + Mat I = _src.getMat(); + _gray.create(I.size(), CV_8UC1); + Mat dst = _gray.getMat(); + + _boost.create(I.size(), CV_8UC3); + Mat color_boost = _boost.getMat(); + + if(!I.data ) + { + cout << "Could not open or find the image" << endl ; + return; + } + if(I.channels() !=3) + { + cout << "Input Color Image" << endl; + return; + } + + float sigma = .02; + int maxIter = 8; + int iterCount = 0; + + int h = I.size().height; + int w = I.size().width; + + Mat img; + Decolor obj; + + double sizefactor; + + if((h + w) > 900) + { + sizefactor = (double)900/(h+w); + resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + else + { + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + + obj.init(); + + vector Cg; + vector < vector > polyGrad; + vector < vector > bc; + vector < vector < int > > comb; + + vector alf; + + +} + diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp new file mode 100644 index 0000000000..5c6cd50cf9 --- /dev/null +++ b/modules/photo/src/contrast_preserve.hpp @@ -0,0 +1,31 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "math.h" +#include +#include + +using namespace std; +using namespace cv; + +class Decolor +{ + public: + Mat kernel; + Mat kernel1; + int order; + void init(); + void grad_system(Mat img, vector < vector < double > > &polyGrad, vector < double > &Cg, vector < vector >& comb); +}; + +void Decolor::init() +{ + kernel = Mat(1,2, CV_32FC1); + kernel1 = Mat(2,1, CV_32FC1); + kernel.at(0,0)=1.0; + kernel.at(0,1)=-1.0; + kernel1.at(0,0)=1.0; + kernel1.at(1,0)=-1.0; + order = 2; + +} From 88aa4a9902dbbf47ee79506996101634cc07881a Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 17 Jun 2013 15:27:52 +0530 Subject: [PATCH 02/27] decolor module updated update3 update4 update4 update5 added test data --- modules/photo/include/opencv2/photo.hpp | 2 +- modules/photo/src/contrast_preserve.cpp | 206 ++++++++---- modules/photo/src/contrast_preserve.hpp | 405 +++++++++++++++++++++++- modules/photo/test/test_decolor.cpp | 34 ++ 4 files changed, 580 insertions(+), 67 deletions(-) create mode 100644 modules/photo/test/test_decolor.cpp diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index e656b93e8a..6f5868dd4c 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -288,7 +288,7 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 271afb5e7e..6d4a2d1313 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -5,72 +5,162 @@ #include #include #include - #include "contrast_preserve.hpp" using namespace std; using namespace cv; -int rounding(double); + +int rounding(double a); int rounding(double a) { - return int(a + 0.5); + return int(a + 0.5); } -void cv::decolor(InputArray _src, OutputArray _gray, OutputArray _boost) +void cv::decolor(InputArray _src, OutputArray _dst) { - Mat I = _src.getMat(); - _gray.create(I.size(), CV_8UC1); - Mat dst = _gray.getMat(); - - _boost.create(I.size(), CV_8UC3); - Mat color_boost = _boost.getMat(); - - if(!I.data ) - { - cout << "Could not open or find the image" << endl ; - return; - } - if(I.channels() !=3) - { - cout << "Input Color Image" << endl; - return; - } - - float sigma = .02; - int maxIter = 8; - int iterCount = 0; - - int h = I.size().height; - int w = I.size().width; - - Mat img; - Decolor obj; - - double sizefactor; - - if((h + w) > 900) - { - sizefactor = (double)900/(h+w); - resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } - else - { - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } - - obj.init(); - - vector Cg; - vector < vector > polyGrad; - vector < vector > bc; - vector < vector < int > > comb; - - vector alf; - - + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); + + if(!I.data ) + { + cout << "Could not open or find the image" << endl ; + return; + } + if(I.channels() !=3) + { + cout << "Input Color Image" << endl; + return; + } + + float sigma = .02; + int maxIter = 8; + int iterCount = 0; + + int h = I.size().height; + int w = I.size().width; + + Decolor obj; + + Mat img; + + double sizefactor; + + if((h + w) > 900) + { + sizefactor = (double)900/(h+w); + resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + else + { + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + } + + obj.init(); + + vector Cg; + vector < vector > polyGrad; + vector < vector > bc; + vector < vector < int > > comb; + + vector alf; + + obj.grad_system(img,polyGrad,Cg,comb); + obj.weak_order(img,alf); + + Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); + obj.wei_update_matrix(polyGrad,Cg,Mt); + + vector wei; + obj.wei_inti(comb,wei); + + //////////////////////////////// main loop starting //////////////////////////////////////// + + while (iterCount < maxIter) + { + iterCount +=1; + + vector G_pos; + vector G_neg; + + vector temp; + vector temp1; + + double val = 0.0; + for(unsigned int i=0;i< polyGrad[0].size();i++) + { + val = 0.0; + for(unsigned int j =0;j EXPsum; + vector EXPterm; + + for(unsigned int i = 0;i temp2; + + for(unsigned int i=0;i wei1; + + for(unsigned int i=0;i< polyGrad.size();i++) + { + val1 = 0.0; + for(unsigned int j =0;j(i,j) * EXPterm[j]); + } + wei1.push_back(val1); + } + + for(unsigned int i =0;i product(vector < vector > &comb, vector &initRGB); + 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 < vector > &comb, int r,int g,int b); + void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); + void weak_order(Mat img, vector &alf); void grad_system(Mat img, vector < vector < double > > &polyGrad, vector < double > &Cg, vector < vector >& comb); + void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); + void wei_inti(vector < vector > &comb, vector &wei); + void grayImContruct(vector &wei, Mat img, Mat &Gray); }; void Decolor::init() { - kernel = Mat(1,2, CV_32FC1); - kernel1 = Mat(2,1, CV_32FC1); - kernel.at(0,0)=1.0; - kernel.at(0,1)=-1.0; - kernel1.at(0,0)=1.0; - kernel1.at(1,0)=-1.0; - order = 2; + kernel = Mat(1,2, CV_32FC1); + kernel1 = Mat(2,1, CV_32FC1); + kernel.at(0,0)=1.0; + kernel.at(0,1)=-1.0; + kernel1.at(0,0)=1.0; + kernel1.at(1,0)=-1.0; + order = 2; + +} + +vector Decolor::product(vector < vector > &comb, vector &initRGB) +{ + vector res; + float dp; + for (unsigned int i=0;i(i,w-1)=0.0; +} + +void Decolor::singleChannelGrady(const Mat &img, Mat& dest) +{ + int w=img.size().width; + int h=img.size().height; + Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); + filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); + for(int j=0;j(h-1,j)=0.0; +} + +void Decolor::gradvector(const Mat &img, vector &grad) +{ + Mat dest= Mat(img.size().height,img.size().width, CV_32FC1); + Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1); + singleChannelGradx(img,dest); + singleChannelGrady(img,dest1); + + Mat d_trans=dest.t(); + Mat d1_trans=dest1.t(); + + int height = d_trans.size().height; + int width = d_trans.size().width; + + for(int i=0;i(i,j)); + + for(int i=0;i(i,j)); + dest.release(); + dest1.release(); +} + +void Decolor::colorGrad(Mat img, vector &Cg) +{ + + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); + + cvtColor(img,lab,COLOR_BGR2Lab); + for(int i=0;i(i,j) = lab.at(i,j*3+0); + a_channel.at(i,j) = lab.at(i,j*3+1); + b_channel.at(i,j) = lab.at(i,j*3+2); + } + + vector ImL; + vector Ima; + vector Imb; + gradvector(l_channel,ImL); + gradvector(a_channel,Ima); + gradvector(b_channel,Imb); + + double res =0.0; + for(unsigned int i=0;i > &comb, int r,int g,int b) +{ + static int idx =0; + comb.push_back( vector () ); + comb.at(idx).push_back( r ); + comb.at(idx).push_back( g ); + comb.at(idx).push_back( b ); + idx++; +} + +void Decolor::add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad) +{ + static int idx1 =0; + polyGrad.push_back( vector () ); + for(unsigned int i=0;i &alf) +{ + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + vector Rg; + vector Gg; + vector Bg; + + vector t1; + vector t2; + vector t3; + + vector tmp1; + vector tmp2; + vector tmp3; + + gradvector(red,Rg); + gradvector(green,Gg); + gradvector(blue,Bg); + double level = .05; + + for(unsigned int i=0;i level) + t1.push_back(1.0); + else + t1.push_back(0.0); + } + for(unsigned int i=0;i level) + t2.push_back(1.0); + else + t2.push_back(0.0); + } + for(unsigned int i=0;i level) + t3.push_back(1.0); + else + t3.push_back(0.0); + } + for(unsigned int i=0;i > &polyGrad, vector < double > &Cg, vector < vector >& comb) +{ + int h = img.size().height; + int w = img.size().width; + colorGrad(img,Cg); + + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + for(int r=0 ;r <=order; r++) + for(int g=0; g<=order;g++) + for(int b =0; b <=order;b++) + { + if((r+g+b)<=order && (r+g+b) > 0) + { + add_vector(comb,r,g,b); + for(int i = 0;i(i,j)= + pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + vector curGrad; + gradvector(curIm,curGrad); + add_to_vector_poly(polyGrad,curGrad); + } + } + + red.release(); + green.release(); + blue.release(); + curIm.release(); +} + +void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) +{ + Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); + Mat A = Mat(poly.size(),poly.size(), CV_32FC1); + + for(unsigned int i =0;i(i,j) = poly[i][j]; + + Mat P_trans = P.t(); + Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); + for(unsigned int i =0;i < poly.size();i++) + { + for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; + } + + A = P*P_trans; + solve(A, B, X, DECOMP_NORMAL); + + P.release(); + A.release(); + B.release(); + +} + +void Decolor::wei_inti(vector < vector > &comb, vector &wei) +{ + vector initRGB; + + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + wei = product(comb,initRGB); + + vector sum; + + for(unsigned int i=0;i &wei, Mat img, Mat &Gray) +{ + + int h=img.size().height; + int w=img.size().width; + + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + int kk =0; + + for(int r =0;r<=order;r++) + for(int g=0;g<=order;g++) + for(int b=0;b<=order;b++) + if((r + g + b) <=order && (r+g+b) > 0) + { + for(int i = 0;i(i,j)=Gray.at(i,j) + + wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + + kk=kk+1; + } + + double minval = INT_MAX; + double maxval = INT_MIN; + + for(int i=0;i(i,j) < minval) + minval = Gray.at(i,j); + + if(Gray.at(i,j) > maxval) + maxval = Gray.at(i,j); + } + + for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); + red.release(); + green.release(); + blue.release(); } diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp new file mode 100644 index 0000000000..3edec908a8 --- /dev/null +++ b/modules/photo/test/test_decolor.cpp @@ -0,0 +1,34 @@ +#include "test_precomp.hpp" +#include "opencv2/photo.hpp" +#include + +using namespace cv; +using namespace std; + +#ifdef DUMP_RESULTS +# define DUMP(image, path) imwrite(path, image) +#else +# define DUMP(image, path) +#endif + + +TEST(Photo_Decolor, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; + string original_path = folder + "color_image_1.png"; + string expected_path = folder + "grayscale_image_1.png"; + + Mat original = imread(original_path, IMREAD_COLOR); + Mat expected = imread(expected_path, IMREAD_GRAYSCALE); + + ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; + ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; + + Mat result; + decolor(original, result); + + DUMP(result, expected_path + ".res.png"); + + ASSERT_EQ(0, norm(result != expected)); +} + From a1b3ba02a702371d473d20545bce6d5a07afd9c6 Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 1 Jul 2013 14:19:03 +0530 Subject: [PATCH 03/27] add color_boost + doc --- modules/photo/doc/decolor.rst | 20 +++++++++++ modules/photo/include/opencv2/photo.hpp | 2 +- modules/photo/src/contrast_preserve.cpp | 46 ++++++++++++++++++++++--- modules/photo/test/test_decolor.cpp | 19 ++++++---- 4 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 modules/photo/doc/decolor.rst diff --git a/modules/photo/doc/decolor.rst b/modules/photo/doc/decolor.rst new file mode 100644 index 0000000000..061b2b18c6 --- /dev/null +++ b/modules/photo/doc/decolor.rst @@ -0,0 +1,20 @@ +Decolorization +============== + +.. highlight:: cpp + +decolor +------- + +Transforms a color image to a grayscale image. It is a basic tool in digital printing, stylized black-and-white photograph rendering, and in many single channel image processing applications. + +.. ocv:function:: void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost ) + + :param src: Input 8-bit 3-channel image. + + :param grayscale: Output 8-bit 1-channel image. + + :param color_boost: Output 8-bit 3-channel image. + +This function is to be applied on color images. + diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 6f5868dd4c..e656b93e8a 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -288,7 +288,7 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale); +CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 6d4a2d1313..570ef8059f 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -17,14 +17,17 @@ int rounding(double a) return int(a + 0.5); } -void cv::decolor(InputArray _src, OutputArray _dst) +void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) { - Mat I = _src.getMat(); + Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC1); Mat dst = _dst.getMat(); - if(!I.data ) - { + _boost.create(I.size(), CV_8UC3); + Mat color_boost = _boost.getMat(); + + if(!I.data ) + { cout << "Could not open or find the image" << endl ; return; } @@ -162,5 +165,40 @@ void cv::decolor(InputArray _src, OutputArray _dst) Gray.convertTo(dst,CV_8UC1,255); + /////////////////////////////////// Contrast Boosting ///////////////////////////////// + + Mat lab = Mat(img.size(),CV_8UC3); + Mat color = Mat(img.size(),CV_8UC3); + Mat l = Mat(img.size(),CV_8UC1); + Mat a = Mat(img.size(),CV_8UC1); + Mat b = Mat(img.size(),CV_8UC1); + + cvtColor(I,lab,COLOR_BGR2Lab); + + int h1 = img.size().height; + int w1 = img.size().width; + + for(int i =0;i(i,j) = lab.at(i,j*3+0); + a.at(i,j) = lab.at(i,j*3+1); + b.at(i,j) = lab.at(i,j*3+2); + } + for(int i =0;i(i,j) = 255.0*Gray.at(i,j); + } + + for(int i =0;i(i,j*3+0) = l.at(i,j); + lab.at(i,j*3+1) = a.at(i,j); + lab.at(i,j*3+2) = b.at(i,j); + } + + cvtColor(lab,color_boost,COLOR_Lab2BGR); } diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index 3edec908a8..94f78a7df0 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -16,19 +16,24 @@ TEST(Photo_Decolor, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; string original_path = folder + "color_image_1.png"; - string expected_path = folder + "grayscale_image_1.png"; + string expected_path1 = folder + "grayscale_image_1.png"; + string expected_path2 = folder + "color_boost_image_1.png"; Mat original = imread(original_path, IMREAD_COLOR); - Mat expected = imread(expected_path, IMREAD_GRAYSCALE); + Mat expected1 = imread(expected_path1, IMREAD_GRAYSCALE); + Mat expected2 = imread(expected_path2, IMREAD_COLOR); ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; - ASSERT_FALSE(expected.empty()) << "Could not load reference image " << expected_path; + ASSERT_FALSE(expected1.empty()) << "Could not load reference image " << expected_path1; + ASSERT_FALSE(expected2.empty()) << "Could not load reference image " << expected_path2; - Mat result; - decolor(original, result); + Mat grayscale, color_boost; + decolor(original, grayscale, color_boost); - DUMP(result, expected_path + ".res.png"); + DUMP(grayscale, expected_path1 + ".grayscale.png"); + DUMP(color_boost, expected_path2 + ".color_boost.png"); - ASSERT_EQ(0, norm(result != expected)); + ASSERT_EQ(0, norm(grayscale != expected1)); + ASSERT_EQ(0, norm(color_boost != expected2)); } From 0802c06571e89b7ae66a7e008d5eb1f4115c7dd6 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 12 Jul 2013 09:18:37 +0530 Subject: [PATCH 04/27] seamless cloning added update1 update1 update4 --- modules/photo/include/opencv2/photo.hpp | 21 + modules/photo/src/seamless_cloning.cpp | 374 +++++++++++ modules/photo/src/seamless_cloning.hpp | 836 ++++++++++++++++++++++++ 3 files changed, 1231 insertions(+) create mode 100644 modules/photo/src/seamless_cloning.cpp create mode 100644 modules/photo/src/seamless_cloning.hpp diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index e656b93e8a..fd05b4ca9b 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -59,6 +59,19 @@ enum INPAINT_TELEA = 1 // A. Telea algorithm }; +enum +{ + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + FEATURE_EXCHANGE = 3 +}; + +enum +{ + FOREGROUND_COLOR_CHANGE = 4, + BACKGROUND_DECOLOR = 5 +}; + //! restores the damaged image areas using one of the available intpainting algorithms CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags ); @@ -290,6 +303,14 @@ CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, OutputArray blend, int flags = 1); + +CV_EXPORTS_W void colorChange(InputArray src, OutputArray dst, int flags = 4, float red = 1.0, float green = 1.0, float blue = 1.0); + +CV_EXPORTS_W void illuminationChange(InputArray _src, OutputArray _dst, float alpha = 0.2, float beta = 0.4); + +CV_EXPORTS_W void textureFlattening(InputArray _src, OutputArray _dst); + } // cv #endif diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp new file mode 100644 index 0000000000..abb9636183 --- /dev/null +++ b/modules/photo/src/seamless_cloning.cpp @@ -0,0 +1,374 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +#include "seamless_cloning.hpp" + +using namespace std; +using namespace cv; + +Mat img0, img1, img2, res, res1, final, final1, blend; + +Point point; +int drag = 0; +int destx, desty; + +int numpts = 100; +Point* pts = new Point[100]; +Point* pts1 = new Point[100]; +Point* pts2 = new Point[100]; + + +int var = 0; +int flag = 0; +int flag1 = 0; + +int minx,miny,maxx,maxy,lenx,leny; +int minxd,minyd,maxxd,maxyd,lenxd,lenyd; + +int channel,num; + +float alpha,beta; + +float red, green, blue; +void mouseHandler(int , int , int , int, void*); +void mouseHandler1(int , int , int , int, void*); +void mouseHandler(int event, int x, int y, int, void*) +{ + + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i(i,j*3+0) = img3.at(i,j); + img4.at(i,j*3+1) = img3.at(i,j); + img4.at(i,j*3+2) = img3.at(i,j); + } + + obj.local_color_change(img4,final,res1,blend,num); + + namedWindow("Background Decolor Image"); + imshow("Background Decolor Image", blend); + waitKey(0); + } + else if(num == 6) + { + Cloning obj; + obj.illum_change(img0,final,res1,blend,alpha,beta); + + namedWindow("Illum Change Image"); + imshow("Illum Change Image", blend); + waitKey(0); + + } + + } + if (event == EVENT_MBUTTONDOWN) + { + for(int i = 0; i < numpts ; i++) + { + pts[i].x=0; + pts[i].y=0; + } + var = 0; + flag1 = 0; + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + imshow("Source", img0); + drag = 0; + } +} + + +void mouseHandler1(int event, int x, int y, int, void*) +{ + + + Mat im1; + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + im1 = img2.clone(); + if (event == EVENT_LBUTTONDOWN) + { + if(flag1 == 1) + { + point = Point(x, y); + + for(int i =0; i < numpts;i++) + pts1[i] = pts[i]; + + int tempx; + int tempy; + for(int i =0; i < flag; i++) + { + tempx = pts1[i+1].x - pts1[i].x; + tempy = pts1[i+1].y - pts1[i].y; + if(i==0) + { + pts2[i+1].x = point.x + tempx; + pts2[i+1].y = point.y + tempy; + } + else if(i>0) + { + pts2[i+1].x = pts2[i].x + tempx; + pts2[i+1].y = pts2[i].y + tempy; + } + + } + + for(int i=flag;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) + { + cout << "Index out of range" << endl; + exit(0); + } + + final1 = Mat::zeros(img2.size(),CV_8UC3); + res = Mat::zeros(img2.size(),CV_8UC1); + for(int i=miny, k=minyd;i<(miny+leny);i++,k++) + for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) + { + for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); + + } + } + + + const Point* pts6[1] = {&pts2[0]}; + fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); + + if(num == 1 || num == 2 || num == 3) + { + Cloning obj; + obj.normal_clone(img2,final1,res,blend,num); + namedWindow("Cloned Image"); + imshow("Cloned Image", blend); + waitKey(0); + } + + for(int i = 0; i < flag ; i++) + { + pts2[i].x=0; + pts2[i].y=0; + } + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + } + + im1.release(); +} + +void cv::seamlessClone(InputArray _src, InputArray _dst, OutputArray _blend, int flags) +{ + Mat src = _src.getMat(); + Mat dest = _dst.getMat(); + _blend.create(dest.size(), CV_8UC3); + blend = _blend.getMat(); + + num = flags; + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + img0 = src; + img2 = dest; + + channel = img0.channels(); + + res = Mat::zeros(img2.size(),CV_8UC1); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + final1 = Mat::zeros(img2.size(),CV_8UC3); + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", mouseHandler, NULL); + imshow("Source", img0); + + /////////// destination image /////////////// + + namedWindow("Destination", 1); + setMouseCallback("Destination", mouseHandler1, NULL); + imshow("Destination",img2); + waitKey(0); + + img0.release(); + img1.release(); + img2.release(); +} + +void cv::colorChange(InputArray _src, OutputArray _dst, int flags, float r, float g, float b) +{ + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + blend = _dst.getMat(); + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + num = flags; + red = r; + green = g; + blue = b; + + img0 = src; + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + namedWindow("Source"); + setMouseCallback("Source", mouseHandler, NULL); + imshow("Source", img0); + + waitKey(0); + + img0.release(); +} + + +void cv::illuminationChange(InputArray _src, OutputArray _dst, float a, float b) +{ + + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + blend = _dst.getMat(); + num = 6; + alpha = a; + beta = b; + + img0 = src; + + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + namedWindow("Source"); + setMouseCallback("Source", mouseHandler, NULL); + imshow("Source", img0); + + waitKey(0); +} +void cv::textureFlattening(InputArray _src, OutputArray _dst) +{ + + Mat src = _src.getMat(); + _dst.create(src.size(), src.type()); + blend = _dst.getMat(); + img0 = src; + + Cloning obj; + obj.texture_flatten(img0,blend); + + namedWindow("Texture Flattened Image"); + imshow("Texture Flattened Image", blend); + waitKey(0); + +} + diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp new file mode 100644 index 0000000000..acff7059b4 --- /dev/null +++ b/modules/photo/src/seamless_cloning.hpp @@ -0,0 +1,836 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include +#include +#include "math.h" + +using namespace std; +using namespace cv; + +#define pi 3.1416 + +class Cloning +{ + + public: + + Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; + Mat smask,srx32,sry32; + Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; + void init(Mat &I, Mat &wmask); + void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + void getGradientx(const Mat &img, Mat &gx); + void getGradienty(const Mat &img, Mat &gy); + void lapx(const Mat &img, Mat &gxx); + void lapy(const Mat &img, Mat &gyy); + void dst(double *gtest, double *gfinal,int h,int w); + void idst(double *gtest, double *gfinal,int h,int w); + void transpose(double *mat, double *mat_t,int h,int w); + void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); + void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red, float green, float blue); + void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); + void texture_flatten(Mat &I, Mat &final); + }; + +void Cloning::getGradientx( const Mat &img, Mat &gx) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } +} +void Cloning::getGradienty( const Mat &img, Mat &gy) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } +} +void Cloning::lapx( const Mat &img, Mat &gxx) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gxx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,(j+1)*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } +} +void Cloning::lapy( const Mat &img, Mat &gyy) +{ + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + gyy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i+1,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } +} + +void Cloning::dst(double *gtest, double *gfinal,int h,int w) +{ + + unsigned long int idx; + + Mat temp = Mat(2*h+2,1,CV_32F); + Mat res = Mat(h,1,CV_32F); + + Mat planes[] = {Mat_(temp), Mat::zeros(temp.size(), CV_32F)}; + + Mat complex1; + int p=0; + for(int i=0;i(0,0) = 0.0; + + for(int j=0,r=1;j(r,0) = gtest[idx]; + } + + temp.at(h+1,0)=0.0; + + for(int j=h-1, r=h+2;j>=0;j--,r++) + { + idx = j*w+i; + temp.at(r,0) = -1*gtest[idx]; + } + + merge(planes, 2, complex1); + + dft(complex1,complex1,0,0); + + Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; + + split(complex1, planes1); + + std::complex two_i = std::sqrt(std::complex(-1)); + + double fac = -2*imag(two_i); + + for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; + } + + for(int q=0,z=0;q(z,0); + } + p++; + } + + temp.release(); + res.release(); + planes[0].release(); + planes[1].release(); + +} + +void Cloning::idst(double *gtest, double *gfinal,int h,int w) +{ + int nn = h+1; + unsigned long int idx; + dst(gtest,gfinal,h,w); + for(int i= 0;i(i,j) = mat[idx]; + } + } + Mat tmp_t = tmp.t(); + + for(int i = 0;i < tmp_t.size().height; i++) + for(int j=0;j(i,j); + } + + tmp.release(); + +} +void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) +{ + + int w = img.size().width; + int h = img.size().height; + + unsigned long int idx,idx1; + + Mat lap = Mat(img.size(),CV_32FC1); + + for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); + + Mat bound = img.clone(); + + for(int i =1;i(i,j) = 0.0; + } + + double *f_bp = new double[h*w]; + + + for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) + + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); + } + + + Mat diff = Mat(h,w,CV_32FC1); + for(int i =0;i(i,j) = (lap.at(i,j) - f_bp[idx]); + } + } + + lap.release(); + + double *gtest = new double[(h-2)*(w-2)]; + for(int i = 0 ; i < h-2;i++) + { + for(int j = 0 ; j < w-2; j++) + { + idx = i*(w-2) + j; + gtest[idx] = diff.at(i+1,j+1); + + } + } + + diff.release(); + ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// + + double *gfinal = new double[(h-2)*(w-2)]; + double *gfinal_t = new double[(h-2)*(w-2)]; + double *denom = new double[(h-2)*(w-2)]; + double *f3 = new double[(h-2)*(w-2)]; + double *f3_t = new double[(h-2)*(w-2)]; + double *img_d = new double[(h)*(w)]; + + dst(gtest,gfinal,h-2,w-2); + + transpose(gfinal,gfinal_t,h-2,w-2); + + dst(gfinal_t,gfinal,w-2,h-2); + + transpose(gfinal,gfinal_t,w-2,h-2); + + int cy=1; + + for(int i = 0 ; i < w-2;i++,cy++) + { + for(int j = 0,cx = 1; j < h-2; j++,cx++) + { + idx = j*(w-2) + i; + denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; + + } + } + + for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) + { + gfinal_t[idx] = gfinal_t[idx]/denom[idx]; + } + + + idst(gfinal_t,f3,h-2,w-2); + + transpose(f3,f3_t,h-2,w-2); + + idst(f3_t,f3,w-2,h-2); + + transpose(f3,f3_t,w-2,h-2); + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + img_d[idx] = (double)img.at(i,j); + } + } + for(int i = 1 ; i < h-1;i++) + { + for(int j = 1 ; j < w-1; j++) + { + idx = i*w + j; + img_d[idx] = 0.0; + } + } + for(int i = 1,id1=0 ; i < h-1;i++,id1++) + { + for(int j = 1,id2=0 ; j < w-1; j++,id2++) + { + idx = i*w + j; + idx1= id1*(w-2) + id2; + img_d[idx] = f3_t[idx1]; + } + } + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + if(img_d[idx] < 0.0) + result.at(i,j) = 0; + else if(img_d[idx] > 255.0) + result.at(i,j) = 255.0; + else + result.at(i,j) = img_d[idx]; + } + } + + delete [] gfinal; + delete [] gfinal_t; + delete [] denom; + delete [] f3; + delete [] f3_t; + delete [] img_d; + delete [] gtest; + delete [] f_bp; + +} + +void Cloning::init(Mat &I, Mat &wmask) +{ + + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + sgx = Mat(I.size(),CV_32FC3); + sgy = Mat(I.size(),CV_32FC3); + + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); + + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + smask = Mat(wmask.size(),CV_32FC1); + srx32 = Mat(I.size(),CV_32FC3); + sry32 = Mat(I.size(),CV_32FC3); + smask1 = Mat(wmask.size(),CV_32FC1); + grx32 = Mat(I.size(),CV_32FC3); + gry32 = Mat(I.size(),CV_32FC3); +} + +void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) +{ + + int channel = I.channels(); + Mat fx = Mat(I.size(),CV_32FC3); + Mat fy = Mat(I.size(),CV_32FC3); + + for(int i=0;i < I.size().height; i++) + for(int j=0; j < I.size().width; j++) + for(int c=0;c(i,j*channel+c) = + (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); + fy.at(i,j*channel+c) = + (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); + } + + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); + + lapx(fx,gxx); + lapy(fy,gyy); + + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } + + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); + + + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); + + clock_t toc = clock(); + + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + + +} +void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) +{ + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + if(num != 3) + { + getGradientx(mask,sgx); + getGradienty(mask,sgy); + } + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + if(num == 1) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + else if(num == 2) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) - sgy.at(i,j*channel+c)) > + abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) + { + + srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) + * smask.at(i,j); + } + else + { + srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) + * smask.at(i,j); + } + } + } + else if(num == 3) + { + Mat gray = Mat(mask.size(),CV_8UC1); + Mat gray8 = Mat(mask.size(),CV_8UC3); + cvtColor(mask, gray, COLOR_BGR2GRAY ); + + for(int i=0;i(i,j*3+0) = gray.at(i,j); + gray8.at(i,j*3+1) = gray.at(i,j); + gray8.at(i,j*3+2) = gray.at(i,j); + } + + + getGradientx(gray8,sgx); + getGradienty(gray8,sgy); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } + +} + +void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red=1.0, float green=1.0, float blue=1.0) +{ + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + if(num == 4) + { + Mat factor = Mat(I.size(),CV_32FC3); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + { + factor.at(i,j*channel+0) = blue; + factor.at(i,j*channel+1) = green; + factor.at(i,j*channel+2) = red; + } + + + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); + sry32.at(i,j*channel+c) = + sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); + } + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } + +} + +void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta) +{ + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + + Mat mag = Mat(I.size(),CV_32FC3); + I.convertTo(mag,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); + } + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) != 0) + { + srx32.at(i,j*channel+c) = + pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + sry32.at(i,j*channel+c) = + pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + } + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } +} + +void Cloning::texture_flatten(Mat &I, Mat &final) +{ + + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + + Mat out = Mat(I.size(),CV_8UC1); + + getGradientx( I, grx); + getGradienty( I, gry); + + Canny( I, out, 30, 45, 3 ); + + int channel = I.channels(); + + for(int i=0;i(i,j) != 255) + { + grx.at(i,j*channel+c) = 0.0; + gry.at(i,j*channel+c) = 0.0; + } + } + + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); + + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); + + lapx(grx,gxx); + lapy(gry,gyy); + + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } + + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); + + + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); + + clock_t toc = clock(); + + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } +} From 5b0ee9e08580efceda96ce4595ea7488450f909e Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 26 Jul 2013 11:33:27 +0530 Subject: [PATCH 05/27] decolor module updated --- modules/photo/src/contrast_preserve.cpp | 42 +- modules/photo/src/contrast_preserve.hpp | 747 +++++++++++++----------- 2 files changed, 422 insertions(+), 367 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 570ef8059f..154f997d8b 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -1,6 +1,7 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" +#include #include "math.h" #include #include @@ -10,11 +11,11 @@ using namespace std; using namespace cv; -int rounding(double a); +double norm(double); -int rounding(double a) +double norm(double E) { - return int(a + 0.5); + return (sqrt(pow(E,2))); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) @@ -37,33 +38,20 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) return; } - float sigma = .02; - int maxIter = 8; + int maxIter = 15; int iterCount = 0; - - int h = I.size().height; - int w = I.size().width; + float tol = .0001; + double E = 0; + double pre_E = std::numeric_limits::infinity(); Decolor obj; Mat img; - - double sizefactor; - if((h + w) > 900) - { - sizefactor = (double)900/(h+w); - resize(I,I,Size(rounding(h*sizefactor),rounding(w*sizefactor))); - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } - else - { - img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - } + img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - obj.init(); + obj.init(); vector Cg; vector < vector > polyGrad; @@ -83,9 +71,10 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) //////////////////////////////// main loop starting //////////////////////////////////////// - while (iterCount < maxIter) + while(norm(E-pre_E) > tol) { iterCount +=1; + pre_E = E; vector G_pos; vector G_neg; @@ -150,6 +139,11 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) for(unsigned int i =0;i maxIter) + break; + G_pos.clear(); G_neg.clear(); temp.clear(); diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 440427fa28..77fc2195ce 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -10,411 +10,472 @@ using namespace cv; class Decolor { - private: - Mat kernel; - Mat kernel1; - int order; - - public: - void init(); - vector product(vector < vector > &comb, vector &initRGB); - 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 < vector > &comb, int r,int g,int b); - void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); - void weak_order(Mat img, vector &alf); - void grad_system(Mat img, vector < vector < double > > &polyGrad, vector < double > &Cg, vector < vector >& comb); - void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); - void wei_inti(vector < vector > &comb, vector &wei); - void grayImContruct(vector &wei, Mat img, Mat &Gray); + private: + Mat kernel; + Mat kernel1; + int order; + + public: + void init(); + vector product(vector < vector > &comb, vector &initRGB); + 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 < vector > &comb, int r,int g,int b); + void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); + void weak_order(Mat img, vector &alf); + void grad_system(Mat img, vector < vector < double > > &polyGrad, + vector < double > &Cg, vector < vector >& comb); + void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); + void wei_inti(vector < vector > &comb, vector &wei); + void grayImContruct(vector &wei, Mat img, Mat &Gray); }; +int rounding(double a); + +int rounding(double a) +{ + return int(a + 0.5); +} + +float sigma = .02; + +double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) +{ + vector P; + + vector temp; + vector temp1; + + double val = 0.0; + for(unsigned int i=0;i< polyGrad[0].size();i++) + { + val = 0.0; + for(unsigned int j =0;j(0,0)=1.0; - kernel.at(0,1)=-1.0; - kernel1.at(0,0)=1.0; - kernel1.at(1,0)=-1.0; - order = 2; + kernel = Mat(1,2, CV_32FC1); + kernel1 = Mat(2,1, CV_32FC1); + kernel.at(0,0)=1.0; + kernel.at(0,1)=-1.0; + kernel1.at(0,0)=1.0; + kernel1.at(1,0)=-1.0; + order = 2; } vector Decolor::product(vector < vector > &comb, vector &initRGB) { - vector res; - float dp; - for (unsigned int i=0;i res; + float dp; + for (unsigned int i=0;i(i,w-1)=0.0; + int w=img.size().width; + int h=img.size().height; + Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1); + filter2D(img, dest, -1, kernel, anchor, 0.0, BORDER_CONSTANT); + for(int i=0;i(i,w-1)=0.0; } void Decolor::singleChannelGrady(const Mat &img, Mat& dest) { - int w=img.size().width; - int h=img.size().height; - Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); - filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); - for(int j=0;j(h-1,j)=0.0; + int w=img.size().width; + int h=img.size().height; + Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); + filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); + for(int j=0;j(h-1,j)=0.0; } void Decolor::gradvector(const Mat &img, vector &grad) { - Mat dest= Mat(img.size().height,img.size().width, CV_32FC1); - Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1); - singleChannelGradx(img,dest); - singleChannelGrady(img,dest1); - - Mat d_trans=dest.t(); - Mat d1_trans=dest1.t(); - - int height = d_trans.size().height; - int width = d_trans.size().width; - - for(int i=0;i(i,j)); - - for(int i=0;i(i,j)); - dest.release(); - dest1.release(); + Mat dest= Mat(img.size().height,img.size().width, CV_32FC1); + Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1); + singleChannelGradx(img,dest); + singleChannelGrady(img,dest1); + + Mat d_trans=dest.t(); + Mat d1_trans=dest1.t(); + + int height = d_trans.size().height; + int width = d_trans.size().width; + + for(int i=0;i(i,j)); + + for(int i=0;i(i,j)); + dest.release(); + dest1.release(); } - + void Decolor::colorGrad(Mat img, vector &Cg) { - Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); - - cvtColor(img,lab,COLOR_BGR2Lab); - for(int i=0;i(i,j) = lab.at(i,j*3+0); - a_channel.at(i,j) = lab.at(i,j*3+1); - b_channel.at(i,j) = lab.at(i,j*3+2); - } - - vector ImL; - vector Ima; - vector Imb; - gradvector(l_channel,ImL); - gradvector(a_channel,Ima); - gradvector(b_channel,Imb); - - double res =0.0; - for(unsigned int i=0;i(i,j) = lab.at(i,j*3+0); + a_channel.at(i,j) = lab.at(i,j*3+1); + b_channel.at(i,j) = lab.at(i,j*3+2); + } + + vector ImL; + vector Ima; + vector Imb; + gradvector(l_channel,ImL); + gradvector(a_channel,Ima); + gradvector(b_channel,Imb); + + double res =0.0; + for(unsigned int i=0;i > &comb, int r,int g,int b) { - static int idx =0; - comb.push_back( vector () ); - comb.at(idx).push_back( r ); - comb.at(idx).push_back( g ); - comb.at(idx).push_back( b ); - idx++; + static int idx =0; + comb.push_back( vector () ); + comb.at(idx).push_back( r ); + comb.at(idx).push_back( g ); + comb.at(idx).push_back( b ); + idx++; } void Decolor::add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad) { - static int idx1 =0; - polyGrad.push_back( vector () ); - for(unsigned int i=0;i() ); + for(unsigned int i=0;i &alf) { - Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } - - vector Rg; - vector Gg; - vector Bg; - - vector t1; - vector t2; - vector t3; - - vector tmp1; - vector tmp2; - vector tmp3; - - gradvector(red,Rg); - gradvector(green,Gg); - gradvector(blue,Bg); - double level = .05; - - for(unsigned int i=0;i level) - t1.push_back(1.0); - else - t1.push_back(0.0); - } - for(unsigned int i=0;i level) - t2.push_back(1.0); - else - t2.push_back(0.0); - } - for(unsigned int i=0;i level) - t3.push_back(1.0); - else - t3.push_back(0.0); - } - for(unsigned int i=0;i 800) + { + sizefactor = (double)800/(h+w); + resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + } + + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + vector Rg; + vector Gg; + vector Bg; + + vector t1; + vector t2; + vector t3; + + vector tmp1; + vector tmp2; + vector tmp3; + + gradvector(red,Rg); + gradvector(green,Gg); + gradvector(blue,Bg); + + double level = .05; + + for(unsigned int i=0;i level) + t1.push_back(1.0); + else + t1.push_back(0.0); + } + for(unsigned int i=0;i level) + t2.push_back(1.0); + else + t2.push_back(0.0); + } + for(unsigned int i=0;i level) + t3.push_back(1.0); + else + t3.push_back(0.0); + } + for(unsigned int i=0;i > &polyGrad, vector < double > &Cg, vector < vector >& comb) +void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, + vector < double > &Cg, vector < vector >& comb) { - int h = img.size().height; - int w = img.size().width; - colorGrad(img,Cg); - - Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } - - for(int r=0 ;r <=order; r++) - for(int g=0; g<=order;g++) - for(int b =0; b <=order;b++) - { - if((r+g+b)<=order && (r+g+b) > 0) - { - add_vector(comb,r,g,b); - for(int i = 0;i(i,j)= - pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); - vector curGrad; - gradvector(curIm,curGrad); - add_to_vector_poly(polyGrad,curGrad); - } - } - - red.release(); - green.release(); - blue.release(); - curIm.release(); + 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(rounding(h*sizefactor),rounding(w*sizefactor))); + } + + h = img.size().height; + w = img.size().width; + colorGrad(img,Cg); + + Mat curIm = Mat(img.size(),CV_32FC1); + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + for(int r=0 ;r <=order; r++) + for(int g=0; g<=order;g++) + for(int b =0; b <=order;b++) + { + if((r+g+b)<=order && (r+g+b) > 0) + { + add_vector(comb,r,g,b); + for(int i = 0;i(i,j)= + pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + vector curGrad; + gradvector(curIm,curGrad); + add_to_vector_poly(polyGrad,curGrad); + } + } + + red.release(); + green.release(); + blue.release(); + curIm.release(); } void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) { - Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); - Mat A = Mat(poly.size(),poly.size(), CV_32FC1); + Mat P = Mat(poly.size(),poly[0].size(), CV_32FC1); + Mat A = Mat(poly.size(),poly.size(), CV_32FC1); - for(unsigned int i =0;i(i,j) = poly[i][j]; + for(unsigned int i =0;i(i,j) = poly[i][j]; - Mat P_trans = P.t(); - Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); - for(unsigned int i =0;i < poly.size();i++) - { - for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; - } + Mat P_trans = P.t(); + Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); + for(unsigned int i =0;i < poly.size();i++) + { + for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; + } - A = P*P_trans; - solve(A, B, X, DECOMP_NORMAL); + A = P*P_trans; + solve(A, B, X, DECOMP_NORMAL); - P.release(); - A.release(); - B.release(); + P.release(); + A.release(); + B.release(); } void Decolor::wei_inti(vector < vector > &comb, vector &wei) { - vector initRGB; + vector initRGB; - initRGB.push_back( .33 ); - initRGB.push_back( .33 ); - initRGB.push_back( .33 ); - wei = product(comb,initRGB); + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + initRGB.push_back( .33 ); + wei = product(comb,initRGB); - vector sum; + vector sum; - for(unsigned int i=0;i &wei, Mat img, Mat &Gray) { - int h=img.size().height; - int w=img.size().width; - - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } - - int kk =0; - - for(int r =0;r<=order;r++) - for(int g=0;g<=order;g++) - for(int b=0;b<=order;b++) - if((r + g + b) <=order && (r+g+b) > 0) - { - for(int i = 0;i(i,j)=Gray.at(i,j) + - wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); - - kk=kk+1; - } - - double minval = INT_MAX; - double maxval = INT_MIN; - - for(int i=0;i(i,j) < minval) - minval = Gray.at(i,j); - - if(Gray.at(i,j) > maxval) - maxval = Gray.at(i,j); - } - - for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); - - red.release(); - green.release(); - blue.release(); + int h=img.size().height; + int w=img.size().width; + + Mat red = Mat(img.size(),CV_32FC1); + Mat green = Mat(img.size(),CV_32FC1); + Mat blue = Mat(img.size(),CV_32FC1); + + for(int i=0;i(i,j) = img.at(i,j*3+2); + green.at(i,j) = img.at(i,j*3+1); + blue.at(i,j) = img.at(i,j*3+0); + } + + int kk =0; + + for(int r =0;r<=order;r++) + for(int g=0;g<=order;g++) + for(int b=0;b<=order;b++) + if((r + g + b) <=order && (r+g+b) > 0) + { + for(int i = 0;i(i,j)=Gray.at(i,j) + + wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); + + kk=kk+1; + } + + double minval = INT_MAX; + double maxval = INT_MIN; + + for(int i=0;i(i,j) < minval) + minval = Gray.at(i,j); + + if(Gray.at(i,j) > maxval) + maxval = Gray.at(i,j); + } + + for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); + + red.release(); + green.release(); + blue.release(); } From e170115ad0d97f76879443184796ca8a23ac7522 Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 5 Aug 2013 12:12:28 +0530 Subject: [PATCH 06/27] new interface added. decolor and cloning module added. Both modules added --- modules/photo/doc/cloning.rst | 88 ++ modules/photo/include/opencv2/photo.hpp | 14 +- modules/photo/src/contrast_preserve.cpp | 42 + modules/photo/src/contrast_preserve.hpp | 42 + modules/photo/src/seamless_cloning.cpp | 505 +++----- modules/photo/src/seamless_cloning.hpp | 1519 ++++++++++++----------- modules/photo/test/test_cloning.cpp | 179 +++ modules/photo/test/test_decolor.cpp | 61 +- samples/cpp/cloning.cpp | 288 +++++ samples/cpp/create_mask.cpp | 145 +++ 10 files changed, 1784 insertions(+), 1099 deletions(-) create mode 100644 modules/photo/doc/cloning.rst create mode 100644 modules/photo/test/test_cloning.cpp create mode 100644 samples/cpp/cloning.cpp create mode 100644 samples/cpp/create_mask.cpp diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst new file mode 100644 index 0000000000..740e1ab64b --- /dev/null +++ b/modules/photo/doc/cloning.rst @@ -0,0 +1,88 @@ +Seamless Cloning +================ + +.. highlight:: cpp + +seamlessClone +------------- +Image editing tasks concern either global changes (color/intensity corrections, filters, deformations) or local changes concerned to a selection. +Here we are interested in achieving local changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless manner. +The extent of the changes ranges from slight distortions to complete replacement by novel content. + +.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray result, int flags) + + :param src: Input 8-bit 3-channel image. + + :param dst: Input 8-bit 3-channel image. + + :param mask: Input 8-bit 1 or 3-channel image. + + :param Point: Point in dst image where object is placed. + + :param result: Output image with the same size and type as ``dst``. + + :param flags: Cloning method that could be one of the following: + + * **NORMAL_CLONE** The power of the method is fully expressed when inserting objects with complex outlines into a new background + + * **MIXED_CLONE** The classic method, color-based selection and alpha + masking might be time consuming and often leaves an undesirable halo. Seamless + cloning, even averaged with the original image, is not effective. Mixed seamless + cloning based on a loose selection proves effective. + + * **FEATURE_EXCHANGE** Feature exchange allows the user to replace easily certain + features of one object by alternative features. + + + +colorChange +----------- +Given an original color image, two differently colored versions of this image can be mixed seamlessly. + +.. ocv:function:: void colorChange( InputArray src, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src`` . + + :param red: R-channel Value + + :param green: G-channel Value + + :param blue: B-channel Value + +RGB values between .5 to 2.5 + + +illuminationChange +------------------ +Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson +solver, modifies locally the apparent illumination of an image. + +.. ocv:function:: void illuminationChange(InputArray src, OutputArray dst, float alpha = 0.2, float beta = 0.4) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + :param alpha: Value ranges between 0-2. + + :param beta: Value ranges between 0-2. + +This is useful to highlight under-exposed foreground objects or to reduce specular reflections. + +textureFlattening +----------------- +By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected +region, giving its contents a flat aspect. + +.. ocv:function:: void textureFlattening(InputArray src, OutputArray dst) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + +**NOTE:** + +The algorithm assumes that the color of the source image is close to that of the destination. This assumption means that when the colors don't match, the source image color gets tinted toward the color of the destination image. diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index fd05b4ca9b..673670354f 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -66,12 +66,6 @@ enum FEATURE_EXCHANGE = 3 }; -enum -{ - FOREGROUND_COLOR_CHANGE = 4, - BACKGROUND_DECOLOR = 5 -}; - //! restores the damaged image areas using one of the available intpainting algorithms CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, OutputArray dst, double inpaintRadius, int flags ); @@ -303,13 +297,13 @@ CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); -CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, OutputArray blend, int flags = 1); +CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, InputArray mask, Point p, OutputArray _blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, OutputArray dst, int flags = 4, float red = 1.0, float green = 1.0, float blue = 1.0); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0); -CV_EXPORTS_W void illuminationChange(InputArray _src, OutputArray _dst, float alpha = 0.2, float beta = 0.4); +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray _src, OutputArray _dst); +CV_EXPORTS_W void textureFlattening(InputArray src, OutputArray dst); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 154f997d8b..9a659691a8 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 77fc2195ce..607b494832 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index abb9636183..c2d6c59b97 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -11,364 +53,161 @@ using namespace std; using namespace cv; -Mat img0, img1, img2, res, res1, final, final1, blend; - -Point point; -int drag = 0; -int destx, desty; - -int numpts = 100; -Point* pts = new Point[100]; -Point* pts1 = new Point[100]; -Point* pts2 = new Point[100]; - - -int var = 0; -int flag = 0; -int flag1 = 0; - -int minx,miny,maxx,maxy,lenx,leny; -int minxd,minyd,maxxd,maxyd,lenxd,lenyd; - -int channel,num; - -float alpha,beta; - -float red, green, blue; -void mouseHandler(int , int , int , int, void*); -void mouseHandler1(int , int , int , int, void*); -void mouseHandler(int event, int x, int y, int, void*) -{ - - if (event == EVENT_LBUTTONDOWN && !drag) - { - if(flag1 == 0) - { - if(var==0) - img1 = img0.clone(); - point = Point(x, y); - circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); - pts[var] = point; - var++; - drag = 1; - if(var>1) - line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); - - imshow("Source", img1); - } - } - - - if (event == EVENT_LBUTTONUP && drag) - { - imshow("Source", img1); - - drag = 0; - } - if (event == EVENT_RBUTTONDOWN) - { - flag1 = 1; - img1 = img0.clone(); - for(int i = var; i < numpts ; i++) - pts[i] = point; - - if(var!=0) - { - const Point* pts3[1] = {&pts[0]}; - polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); - } - - for(int i=0;i(i,j*3+0) = img3.at(i,j); - img4.at(i,j*3+1) = img3.at(i,j); - img4.at(i,j*3+2) = img3.at(i,j); - } - - obj.local_color_change(img4,final,res1,blend,num); - - namedWindow("Background Decolor Image"); - imshow("Background Decolor Image", blend); - waitKey(0); - } - else if(num == 6) - { - Cloning obj; - obj.illum_change(img0,final,res1,blend,alpha,beta); - - namedWindow("Illum Change Image"); - imshow("Illum Change Image", blend); - waitKey(0); - - } - - } - if (event == EVENT_MBUTTONDOWN) - { - for(int i = 0; i < numpts ; i++) - { - pts[i].x=0; - pts[i].y=0; - } - var = 0; - flag1 = 0; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - imshow("Source", img0); - drag = 0; - } -} - - -void mouseHandler1(int event, int x, int y, int, void*) -{ - - - Mat im1; - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - im1 = img2.clone(); - if (event == EVENT_LBUTTONDOWN) - { - if(flag1 == 1) - { - point = Point(x, y); - - for(int i =0; i < numpts;i++) - pts1[i] = pts[i]; - - int tempx; - int tempy; - for(int i =0; i < flag; i++) - { - tempx = pts1[i+1].x - pts1[i].x; - tempy = pts1[i+1].y - pts1[i].y; - if(i==0) - { - pts2[i+1].x = point.x + tempx; - pts2[i+1].y = point.y + tempy; - } - else if(i>0) - { - pts2[i+1].x = pts2[i].x + tempx; - pts2[i+1].y = pts2[i].y + tempy; - } - - } - - for(int i=flag;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) - { - cout << "Index out of range" << endl; - exit(0); - } - - final1 = Mat::zeros(img2.size(),CV_8UC3); - res = Mat::zeros(img2.size(),CV_8UC1); - for(int i=miny, k=minyd;i<(miny+leny);i++,k++) - for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) - { - for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); - - } - } - - - const Point* pts6[1] = {&pts2[0]}; - fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); - - if(num == 1 || num == 2 || num == 3) - { - Cloning obj; - obj.normal_clone(img2,final1,res,blend,num); - namedWindow("Cloned Image"); - imshow("Cloned Image", blend); - waitKey(0); - } - - for(int i = 0; i < flag ; i++) - { - pts2[i].x=0; - pts2[i].y=0; - } - - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - } - - im1.release(); -} - -void cv::seamlessClone(InputArray _src, InputArray _dst, OutputArray _blend, int flags) +void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags) { Mat src = _src.getMat(); Mat dest = _dst.getMat(); + Mat mask = _mask.getMat(); _blend.create(dest.size(), CV_8UC3); - blend = _blend.getMat(); - - num = flags; - - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - - img0 = src; - img2 = dest; - - channel = img0.channels(); - - res = Mat::zeros(img2.size(),CV_8UC1); - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); - final1 = Mat::zeros(img2.size(),CV_8UC3); - //////////// source image /////////////////// - - namedWindow("Source", 1); - setMouseCallback("Source", mouseHandler, NULL); - imshow("Source", img0); - - /////////// destination image /////////////// - - namedWindow("Destination", 1); - setMouseCallback("Destination", mouseHandler1, NULL); - imshow("Destination",img2); - waitKey(0); - - img0.release(); - img1.release(); - img2.release(); + Mat blend = _blend.getMat(); + + int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN; + int h = mask.size().height; + int w = mask.size().width; + + Mat gray = Mat(mask.size(),CV_8UC1); + Mat dst_mask = Mat::zeros(dest.size(),CV_8UC1); + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); + Mat cd_mask = Mat::zeros(dest.size(),CV_8UC3); + + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; + + for(int i=0;i(i,j) == 255) + { + minx = std::min(minx,i); + maxx = std::max(maxx,i); + miny = std::min(miny,j); + maxy = std::max(maxy,j); + } + } + } + + int lenx = maxx - minx; + int leny = maxy - miny; + + int minxd = p.y - lenx/2; + int maxxd = p.y + lenx/2; + int minyd = p.x - leny/2; + int maxyd = p.x + leny/2; + + if(minxd < 0 || minyd < 0 || maxxd > dest.size().height || maxyd > dest.size().width) + { + cout << "Index out of range" << endl; + exit(0); + } + + for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) + for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) + { + dst_mask.at(k,l) = gray.at(i,j); + } + + int channel = 3; + + for(int i=minx;i<(minx+lenx);i++) + for(int j=miny;j<(miny+leny);j++) + { + for(int c=0;c<3;c++) + { + if(gray.at(i,j) == 255) + cs_mask.at(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) + for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) + { + for(int c=0;c(k,l*channel+c) = cs_mask.at(i,j*channel+c); + } + + Cloning obj; + obj.normal_clone(dest,cd_mask,dst_mask,blend,flags); } -void cv::colorChange(InputArray _src, OutputArray _dst, int flags, float r, float g, float b) +void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b) { Mat src = _src.getMat(); + Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); - blend = _dst.getMat(); + Mat blend = _dst.getMat(); - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - - num = flags; - red = r; - green = g; - blue = b; - - img0 = src; - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); - - namedWindow("Source"); - setMouseCallback("Source", mouseHandler, NULL); - imshow("Source", img0); - - waitKey(0); - - img0.release(); + float red = r; + float green = g; + float blue = b; + + Mat gray = Mat::zeros(mask.size(),CV_8UC1); + cvtColor(mask, gray, COLOR_BGR2GRAY); + + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); + + int channel = 3; + for(int i=0;i(i,j) == 255) + { + for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + } + + Cloning obj; + obj.local_color_change(src,cs_mask,gray,blend,red,green,blue); } -void cv::illuminationChange(InputArray _src, OutputArray _dst, float a, float b) +void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b) { Mat src = _src.getMat(); + Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); - blend = _dst.getMat(); - num = 6; - alpha = a; - beta = b; + Mat blend = _dst.getMat(); + float alpha = a; + float beta = b; + + Mat gray = Mat::zeros(mask.size(),CV_8UC1); + cvtColor(mask, gray, COLOR_BGR2GRAY); + + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); + + int channel = 3; + for(int i=0;i(i,j) == 255) + { + for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + } + + Cloning obj; + obj.illum_change(src,cs_mask,gray,blend,alpha,beta); - img0 = src; - - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); - - namedWindow("Source"); - setMouseCallback("Source", mouseHandler, NULL); - imshow("Source", img0); - - waitKey(0); } void cv::textureFlattening(InputArray _src, OutputArray _dst) { Mat src = _src.getMat(); _dst.create(src.size(), src.type()); - blend = _dst.getMat(); - img0 = src; + Mat blend = _dst.getMat(); Cloning obj; - obj.texture_flatten(img0,blend); - - namedWindow("Texture Flattened Image"); - imshow("Texture Flattened Image", blend); - waitKey(0); - + obj.texture_flatten(src,blend); } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index acff7059b4..61fdad9c5e 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -15,822 +57,819 @@ using namespace cv; class Cloning { - - public: - - Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; - Mat smask,srx32,sry32; - Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; - void init(Mat &I, Mat &wmask); - void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); - void getGradientx(const Mat &img, Mat &gx); - void getGradienty(const Mat &img, Mat &gy); - void lapx(const Mat &img, Mat &gxx); - void lapy(const Mat &img, Mat &gyy); - void dst(double *gtest, double *gfinal,int h,int w); - void idst(double *gtest, double *gfinal,int h,int w); - void transpose(double *mat, double *mat_t,int h,int w); - void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); - void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); - void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red, float green, float blue); - void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &final); - }; - + + public: + + Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; + Mat smask,srx32,sry32; + Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; + void init(Mat &I, Mat &wmask); + void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + void getGradientx(const Mat &img, Mat &gx); + void getGradienty(const Mat &img, Mat &gy); + void lapx(const Mat &img, Mat &gxx); + void lapy(const Mat &img, Mat &gyy); + void dst(double *gtest, double *gfinal,int h,int w); + void idst(double *gtest, double *gfinal,int h,int w); + void transpose(double *mat, double *mat_t,int h,int w); + void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); + void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue); + void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); + void texture_flatten(Mat &I, Mat &final); +}; + void Cloning::getGradientx( const Mat &img, Mat &gx) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); - - gx = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i,j*channel+c) = - (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); - } + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } } void Cloning::getGradienty( const Mat &img, Mat &gy) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); - - gy = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i,j*channel+c) = - (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); - - } + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } } void Cloning::lapx( const Mat &img, Mat &gxx) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); - - gxx = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i,(j+1)*channel+c) = - (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); - } + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + + gxx = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i,(j+1)*channel+c) = + (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); + } } void Cloning::lapy( const Mat &img, Mat &gyy) { - int w = img.size().width; - int h = img.size().height; - int channel = img.channels(); - gyy = Mat::zeros(img.size(),CV_32FC3); - for(int i=0;i(i+1,j*channel+c) = - (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); - - } + int w = img.size().width; + int h = img.size().height; + int channel = img.channels(); + gyy = Mat::zeros(img.size(),CV_32FC3); + for(int i=0;i(i+1,j*channel+c) = + (float)img.at((i+1),j*channel+c) - (float)img.at(i,j*channel+c); + + } } void Cloning::dst(double *gtest, double *gfinal,int h,int w) { - unsigned long int idx; + unsigned long int idx; + + Mat temp = Mat(2*h+2,1,CV_32F); + Mat res = Mat(h,1,CV_32F); + + Mat planes[] = {Mat_(temp), Mat::zeros(temp.size(), CV_32F)}; + + Mat complex1; + int p=0; + for(int i=0;i(0,0) = 0.0; - Mat temp = Mat(2*h+2,1,CV_32F); - Mat res = Mat(h,1,CV_32F); + for(int j=0,r=1;j(r,0) = gtest[idx]; + } - Mat planes[] = {Mat_(temp), Mat::zeros(temp.size(), CV_32F)}; + temp.at(h+1,0)=0.0; - Mat complex1; - int p=0; - for(int i=0;i(0,0) = 0.0; - - for(int j=0,r=1;j(r,0) = gtest[idx]; - } + for(int j=h-1, r=h+2;j>=0;j--,r++) + { + idx = j*w+i; + temp.at(r,0) = -1*gtest[idx]; + } - temp.at(h+1,0)=0.0; + merge(planes, 2, complex1); - for(int j=h-1, r=h+2;j>=0;j--,r++) - { - idx = j*w+i; - temp.at(r,0) = -1*gtest[idx]; - } - - merge(planes, 2, complex1); + dft(complex1,complex1,0,0); - dft(complex1,complex1,0,0); + Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; - Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; - - split(complex1, planes1); + split(complex1, planes1); - std::complex two_i = std::sqrt(std::complex(-1)); + std::complex two_i = std::sqrt(std::complex(-1)); - double fac = -2*imag(two_i); + double fac = -2*imag(two_i); - for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; - } + for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; + } - for(int q=0,z=0;q(z,0); - } - p++; - } + for(int q=0,z=0;q(z,0); + } + p++; + } - temp.release(); - res.release(); - planes[0].release(); - planes[1].release(); + temp.release(); + res.release(); + planes[0].release(); + planes[1].release(); } void Cloning::idst(double *gtest, double *gfinal,int h,int w) { - int nn = h+1; - unsigned long int idx; - dst(gtest,gfinal,h,w); - for(int i= 0;i(i,j) = mat[idx]; - } - } - Mat tmp_t = tmp.t(); + idx = i*(w) + j; + tmp.at(i,j) = mat[idx]; + } + } + Mat tmp_t = tmp.t(); - for(int i = 0;i < tmp_t.size().height; i++) - for(int j=0;j(i,j); - } + for(int i = 0;i < tmp_t.size().height; i++) + for(int j=0;j(i,j); + } - tmp.release(); + tmp.release(); } void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { - int w = img.size().width; - int h = img.size().height; + int w = img.size().width; + int h = img.size().height; + + unsigned long int idx,idx1; + + Mat lap = Mat(img.size(),CV_32FC1); + + for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); + + Mat bound = img.clone(); + + for(int i =1;i(i,j) = 0.0; + } + + double *f_bp = new double[h*w]; - unsigned long int idx,idx1; - Mat lap = Mat(img.size(),CV_32FC1); - - for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); - - Mat bound = img.clone(); - - for(int i =1;i(i,j) = 0.0; - } - - double *f_bp = new double[h*w]; - - - for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) - + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); - } - - - Mat diff = Mat(h,w,CV_32FC1); - for(int i =0;i(i,j) = (lap.at(i,j) - f_bp[idx]); - } - } - - lap.release(); - - double *gtest = new double[(h-2)*(w-2)]; - for(int i = 0 ; i < h-2;i++) - { - for(int j = 0 ; j < w-2; j++) - { - idx = i*(w-2) + j; - gtest[idx] = diff.at(i+1,j+1); - - } - } - - diff.release(); - ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// - - double *gfinal = new double[(h-2)*(w-2)]; - double *gfinal_t = new double[(h-2)*(w-2)]; - double *denom = new double[(h-2)*(w-2)]; - double *f3 = new double[(h-2)*(w-2)]; - double *f3_t = new double[(h-2)*(w-2)]; - double *img_d = new double[(h)*(w)]; - - dst(gtest,gfinal,h-2,w-2); - - transpose(gfinal,gfinal_t,h-2,w-2); - - dst(gfinal_t,gfinal,w-2,h-2); - - transpose(gfinal,gfinal_t,w-2,h-2); - - int cy=1; - - for(int i = 0 ; i < w-2;i++,cy++) - { - for(int j = 0,cx = 1; j < h-2; j++,cx++) - { - idx = j*(w-2) + i; - denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; - - } - } - - for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) - { - gfinal_t[idx] = gfinal_t[idx]/denom[idx]; - } - - - idst(gfinal_t,f3,h-2,w-2); - - transpose(f3,f3_t,h-2,w-2); - - idst(f3_t,f3,w-2,h-2); - - transpose(f3,f3_t,w-2,h-2); - - for(int i = 0 ; i < h;i++) - { - for(int j = 0 ; j < w; j++) - { - idx = i*w + j; - img_d[idx] = (double)img.at(i,j); - } - } - for(int i = 1 ; i < h-1;i++) - { - for(int j = 1 ; j < w-1; j++) - { - idx = i*w + j; - img_d[idx] = 0.0; - } - } - for(int i = 1,id1=0 ; i < h-1;i++,id1++) - { - for(int j = 1,id2=0 ; j < w-1; j++,id2++) - { - idx = i*w + j; - idx1= id1*(w-2) + id2; - img_d[idx] = f3_t[idx1]; - } - } - - for(int i = 0 ; i < h;i++) - { - for(int j = 0 ; j < w; j++) - { - idx = i*w + j; - if(img_d[idx] < 0.0) - result.at(i,j) = 0; - else if(img_d[idx] > 255.0) - result.at(i,j) = 255.0; - else - result.at(i,j) = img_d[idx]; - } - } - - delete [] gfinal; - delete [] gfinal_t; - delete [] denom; - delete [] f3; - delete [] f3_t; - delete [] img_d; - delete [] gtest; - delete [] f_bp; + for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) + + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); + } + + + Mat diff = Mat(h,w,CV_32FC1); + for(int i =0;i(i,j) = (lap.at(i,j) - f_bp[idx]); + } + } + + lap.release(); + + double *gtest = new double[(h-2)*(w-2)]; + for(int i = 0 ; i < h-2;i++) + { + for(int j = 0 ; j < w-2; j++) + { + idx = i*(w-2) + j; + gtest[idx] = diff.at(i+1,j+1); + + } + } + + diff.release(); + ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// + + double *gfinal = new double[(h-2)*(w-2)]; + double *gfinal_t = new double[(h-2)*(w-2)]; + double *denom = new double[(h-2)*(w-2)]; + double *f3 = new double[(h-2)*(w-2)]; + double *f3_t = new double[(h-2)*(w-2)]; + double *img_d = new double[(h)*(w)]; + + dst(gtest,gfinal,h-2,w-2); + + transpose(gfinal,gfinal_t,h-2,w-2); + + dst(gfinal_t,gfinal,w-2,h-2); + + transpose(gfinal,gfinal_t,w-2,h-2); + + int cy=1; + + for(int i = 0 ; i < w-2;i++,cy++) + { + for(int j = 0,cx = 1; j < h-2; j++,cx++) + { + idx = j*(w-2) + i; + denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; + + } + } + + for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) + { + gfinal_t[idx] = gfinal_t[idx]/denom[idx]; + } + + + idst(gfinal_t,f3,h-2,w-2); + + transpose(f3,f3_t,h-2,w-2); + + idst(f3_t,f3,w-2,h-2); + + transpose(f3,f3_t,w-2,h-2); + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + img_d[idx] = (double)img.at(i,j); + } + } + for(int i = 1 ; i < h-1;i++) + { + for(int j = 1 ; j < w-1; j++) + { + idx = i*w + j; + img_d[idx] = 0.0; + } + } + for(int i = 1,id1=0 ; i < h-1;i++,id1++) + { + for(int j = 1,id2=0 ; j < w-1; j++,id2++) + { + idx = i*w + j; + idx1= id1*(w-2) + id2; + img_d[idx] = f3_t[idx1]; + } + } + + for(int i = 0 ; i < h;i++) + { + for(int j = 0 ; j < w; j++) + { + idx = i*w + j; + if(img_d[idx] < 0.0) + result.at(i,j) = 0; + else if(img_d[idx] > 255.0) + result.at(i,j) = 255.0; + else + result.at(i,j) = img_d[idx]; + } + } + + delete [] gfinal; + delete [] gfinal_t; + delete [] denom; + delete [] f3; + delete [] f3_t; + delete [] img_d; + delete [] gtest; + delete [] f_bp; } void Cloning::init(Mat &I, Mat &wmask) { - grx = Mat(I.size(),CV_32FC3); - gry = Mat(I.size(),CV_32FC3); - sgx = Mat(I.size(),CV_32FC3); - sgy = Mat(I.size(),CV_32FC3); - - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); - - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } - - smask = Mat(wmask.size(),CV_32FC1); - srx32 = Mat(I.size(),CV_32FC3); - sry32 = Mat(I.size(),CV_32FC3); - smask1 = Mat(wmask.size(),CV_32FC1); - grx32 = Mat(I.size(),CV_32FC3); - gry32 = Mat(I.size(),CV_32FC3); + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + sgx = Mat(I.size(),CV_32FC3); + sgy = Mat(I.size(),CV_32FC3); + + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); + + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + smask = Mat(wmask.size(),CV_32FC1); + srx32 = Mat(I.size(),CV_32FC3); + sry32 = Mat(I.size(),CV_32FC3); + smask1 = Mat(wmask.size(),CV_32FC1); + grx32 = Mat(I.size(),CV_32FC3); + gry32 = Mat(I.size(),CV_32FC3); } void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) { - int channel = I.channels(); - Mat fx = Mat(I.size(),CV_32FC3); - Mat fy = Mat(I.size(),CV_32FC3); - - for(int i=0;i < I.size().height; i++) - for(int j=0; j < I.size().width; j++) - for(int c=0;c(i,j*channel+c) = - (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); - fy.at(i,j*channel+c) = - (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); - } - - Mat gxx = Mat(I.size(),CV_32FC3); - Mat gyy = Mat(I.size(),CV_32FC3); - - lapx(fx,gxx); - lapy(fy,gyy); - - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } - - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); - - clock_t tic = clock(); - - - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); - - clock_t toc = clock(); - - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + int channel = I.channels(); + Mat fx = Mat(I.size(),CV_32FC3); + Mat fy = Mat(I.size(),CV_32FC3); + + for(int i=0;i < I.size().height; i++) + for(int j=0; j < I.size().width; j++) + for(int c=0;c(i,j*channel+c) = + (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); + fy.at(i,j*channel+c) = + (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); + } + + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); + + lapx(fx,gxx); + lapy(fy,gyy); + + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } + + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); + + + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); + + clock_t toc = clock(); + + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); } void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); - - getGradientx(I,grx); - getGradienty(I,gry); - - if(num != 3) - { - getGradientx(mask,sgx); - getGradienty(mask,sgy); - } - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - if(num == 1) - { - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - } - else if(num == 2) - { - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) - sgy.at(i,j*channel+c)) > - abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) - { - - srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) - * smask.at(i,j); - } - else - { - srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) - * smask.at(i,j); - } - } - } - else if(num == 3) - { - Mat gray = Mat(mask.size(),CV_8UC1); - Mat gray8 = Mat(mask.size(),CV_8UC3); - cvtColor(mask, gray, COLOR_BGR2GRAY ); - - for(int i=0;i(i,j*3+0) = gray.at(i,j); - gray8.at(i,j*3+1) = gray.at(i,j); - gray8.at(i,j*3+2) = gray.at(i,j); - } - - - getGradientx(gray8,sgx); - getGradienty(gray8,sgy); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - } - - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + if(num != 3) + { + getGradientx(mask,sgx); + getGradienty(mask,sgy); + } + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + if(num == 1) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + else if(num == 2) + { + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) - sgy.at(i,j*channel+c)) > + abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) + { + + srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) + * smask.at(i,j); + } + else + { + srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) + * smask.at(i,j); + sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) + * smask.at(i,j); + } + } + } + else if(num == 3) + { + Mat gray = Mat(mask.size(),CV_8UC1); + Mat gray8 = Mat(mask.size(),CV_8UC3); + cvtColor(mask, gray, COLOR_BGR2GRAY ); + + for(int i=0;i(i,j*3+0) = gray.at(i,j); + gray8.at(i,j*3+1) = gray.at(i,j); + gray8.at(i,j*3+2) = gray.at(i,j); + } + + + getGradientx(gray8,sgx); + getGradienty(gray8,sgy); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } -void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num, float red=1.0, float green=1.0, float blue=1.0) +void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red=1.0, float green=1.0, float blue=1.0) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); - - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - if(num == 4) - { - Mat factor = Mat(I.size(),CV_32FC3); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - { - factor.at(i,j*channel+0) = blue; - factor.at(i,j*channel+1) = green; - factor.at(i,j*channel+2) = red; - } - - - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); - sry32.at(i,j*channel+c) = - sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); - } - } - - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + Mat factor = Mat(I.size(),CV_32FC3); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + { + factor.at(i,j*channel+0) = blue; + factor.at(i,j*channel+1) = green; + factor.at(i,j*channel+2) = red; + } + + + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); + sry32.at(i,j*channel+c) = + sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); - - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - - Mat mag = Mat(I.size(),CV_32FC3); - I.convertTo(mag,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); - } - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) != 0) - { - srx32.at(i,j*channel+c) = - pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - sry32.at(i,j*channel+c) = - pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - } - } - - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + init(I,wmask); + + int w = I.size().width; + int h = I.size().height; + int channel = I.channels(); + + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + + + Mat mag = Mat(I.size(),CV_32FC3); + I.convertTo(mag,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); + } + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) != 0) + { + srx32.at(i,j*channel+c) = + pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + sry32.at(i,j*channel+c) = + pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + } + } + + bitwise_not(wmask,wmask); + + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); + + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } + + calc(I,grx32,gry32,srx32,sry32); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } void Cloning::texture_flatten(Mat &I, Mat &final) { - grx = Mat(I.size(),CV_32FC3); - gry = Mat(I.size(),CV_32FC3); - - Mat out = Mat(I.size(),CV_8UC1); - - getGradientx( I, grx); - getGradienty( I, gry); - - Canny( I, out, 30, 45, 3 ); - - int channel = I.channels(); - - for(int i=0;i(i,j) != 255) - { - grx.at(i,j*channel+c) = 0.0; - gry.at(i,j*channel+c) = 0.0; - } - } - - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); - - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } - - Mat gxx = Mat(I.size(),CV_32FC3); - Mat gyy = Mat(I.size(),CV_32FC3); - - lapx(grx,gxx); - lapy(gry,gyy); - - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } - - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); - - clock_t tic = clock(); - - - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); - - clock_t toc = clock(); - - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + grx = Mat(I.size(),CV_32FC3); + gry = Mat(I.size(),CV_32FC3); + + Mat out = Mat(I.size(),CV_8UC1); + + getGradientx( I, grx); + getGradienty( I, gry); + + Canny( I, out, 30, 45, 3 ); + + int channel = I.channels(); + + for(int i=0;i(i,j) != 255) + { + grx.at(i,j*channel+c) = 0.0; + gry.at(i,j*channel+c) = 0.0; + } + } + + r_channel = Mat::zeros(I.size(),CV_8UC1); + g_channel = Mat::zeros(I.size(),CV_8UC1); + b_channel = Mat::zeros(I.size(),CV_8UC1); + + for(int i=0;i(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); + b_channel.at(i,j) = I.at(i,j*3+2); + } + + Mat gxx = Mat(I.size(),CV_32FC3); + Mat gyy = Mat(I.size(),CV_32FC3); + + lapx(grx,gxx); + lapy(gry,gyy); + + rx_channel = Mat(I.size(),CV_32FC1); + gx_channel = Mat(I.size(),CV_32FC1); + bx_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); + bx_channel.at(i,j) = gxx.at(i,j*3+2); + } + + ry_channel = Mat(I.size(),CV_32FC1); + gy_channel = Mat(I.size(),CV_32FC1); + by_channel = Mat(I.size(),CV_32FC1); + + for(int i=0;i(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); + by_channel.at(i,j) = gyy.at(i,j*3+2); + } + + resultr = Mat(I.size(),CV_8UC1); + resultg = Mat(I.size(),CV_8UC1); + resultb = Mat(I.size(),CV_8UC1); + + clock_t tic = clock(); + + + poisson_solver(r_channel,rx_channel, ry_channel,resultr); + poisson_solver(g_channel,gx_channel, gy_channel,resultg); + poisson_solver(b_channel,bx_channel, by_channel,resultb); + + clock_t toc = clock(); + + printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + + for(int i=0;i(i,j*3+0) = resultr.at(i,j); + final.at(i,j*3+1) = resultg.at(i,j); + final.at(i,j*3+2) = resultb.at(i,j); + } } diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp new file mode 100644 index 0000000000..583a069aee --- /dev/null +++ b/modules/photo/test/test_cloning.cpp @@ -0,0 +1,179 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#include "test_precomp.hpp" +#include "opencv2/photo.hpp" +#include + +using namespace cv; +using namespace std; + + +TEST(Photo_SeamlessClone_normal, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Normal_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3; + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + seamlessClone(source, destination, mask, p, result, 1); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_mixed, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Mixed_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3; + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + seamlessClone(source, destination, mask, p, result, 2); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_featureExchange, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Feature_Exchange/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3; + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + seamlessClone(source, destination, mask, p, result, 3); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_colorChange, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Color_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; + + Mat result; + colorChange(source, mask, result, 1.5, .5, .5); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_illuminationChange, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Illumination_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; + + Mat result; + illuminationChange(source, mask, result, .2, .4); + + imwrite(folder + "cloned.png", result); + +} + +TEST(Photo_SeamlessClone_textureFlattening, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/"; + string original_path = folder + "source1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path; + + Mat result; + textureFlattening(source, result); + + imwrite(folder + "cloned.png", result); + +} + diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index 94f78a7df0..c218c6a4fa 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -1,3 +1,45 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + #include "test_precomp.hpp" #include "opencv2/photo.hpp" #include @@ -5,35 +47,22 @@ using namespace cv; using namespace std; -#ifdef DUMP_RESULTS -# define DUMP(image, path) imwrite(path, image) -#else -# define DUMP(image, path) -#endif - TEST(Photo_Decolor, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/"; string original_path = folder + "color_image_1.png"; - string expected_path1 = folder + "grayscale_image_1.png"; - string expected_path2 = folder + "color_boost_image_1.png"; Mat original = imread(original_path, IMREAD_COLOR); - Mat expected1 = imread(expected_path1, IMREAD_GRAYSCALE); - Mat expected2 = imread(expected_path2, IMREAD_COLOR); ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path; - ASSERT_FALSE(expected1.empty()) << "Could not load reference image " << expected_path1; - ASSERT_FALSE(expected2.empty()) << "Could not load reference image " << expected_path2; + ASSERT_FALSE(original.channels()!=3) << "Load color input image " << original_path; Mat grayscale, color_boost; decolor(original, grayscale, color_boost); - DUMP(grayscale, expected_path1 + ".grayscale.png"); - DUMP(color_boost, expected_path2 + ".color_boost.png"); + imwrite(folder + "grayscale.png",grayscale); + imwrite(folder + "color_boost.png",color_boost); - ASSERT_EQ(0, norm(grayscale != expected1)); - ASSERT_EQ(0, norm(color_boost != expected2)); } diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp new file mode 100644 index 0000000000..70725d8e74 --- /dev/null +++ b/samples/cpp/cloning.cpp @@ -0,0 +1,288 @@ +/* +* cloning.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV seamless cloning +* module. +* Flags: +* 1- NORMAL_CLONE +* 2- MIXED_CLONE +* 3- FEATURE_EXCHANGE + +* The program takes as input a source and a destination image +* and ouputs the cloned image. + +* Step 1: +* -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button. +* -> To set the Polygon ROI, click the right mouse button. +* -> To reset the region selected, click the middle mouse button. + +* Step 2: +* -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button. +* -> To get the cloned result, click the right mouse button. + +* Result: The cloned image will be displayed. +*/ + +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +Mat img0, img1, img2, res, res1, final, final1, blend; + +Point point; +int drag = 0; +int destx, desty; + +int numpts = 100; +Point* pts = new Point[100]; +Point* pts2 = new Point[100]; +Point* pts_diff = new Point[100]; + + +int var = 0; +int flag = 0; +int flag1 = 0; + +int minx,miny,maxx,maxy,lenx,leny; +int minxd,minyd,maxxd,maxyd,lenxd,lenyd; + +int channel,num; + +void source(int event, int x, int y, int, void*) +{ + + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) + { + cout << "Index out of range" << endl; + exit(0); + } + + final1 = Mat::zeros(img2.size(),CV_8UC3); + res = Mat::zeros(img2.size(),CV_8UC1); + for(int i=miny, k=minyd;i<(miny+leny);i++,k++) + for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) + { + for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); + + } + } + + + const Point* pts6[1] = {&pts2[0]}; + fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); + + if(num == 1 || num == 2 || num == 3) + { + seamlessClone(img0,img2,res1,point,blend,num); + imshow("Cloned Image", blend); + imwrite("cloned.png",blend); + waitKey(0); + } + + for(int i = 0; i < flag ; i++) + { + pts2[i].x=0; + pts2[i].y=0; + } + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + } + + im1.release(); +} + +int main(int argc, char **argv) +{ + + if (argc != 3) + { + cout << "usage: " << argv[0] << " " << " " << endl; + exit(1); + } + + Mat src = imread(argv[1]); + Mat dest = imread(argv[2]); + + cout << "Flags:" << endl; + cout << "1- NORMAL_CLONE" << endl; + cout << "2- MIXED_CLONE" << endl; + cout << "3- FEATURE_EXCHANGE" << endl << endl; + + cout << "Enter Flag:"; + cin >> num; + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + img0 = src; + img2 = dest; + + channel = img0.channels(); + + res = Mat::zeros(img2.size(),CV_8UC1); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + final1 = Mat::zeros(img2.size(),CV_8UC3); + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + /////////// destination image /////////////// + + namedWindow("Destination", 1); + setMouseCallback("Destination", destination, NULL); + imshow("Destination",img2); + waitKey(0); + + img0.release(); + img1.release(); + img2.release(); +} diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp new file mode 100644 index 0000000000..03055e99e0 --- /dev/null +++ b/samples/cpp/create_mask.cpp @@ -0,0 +1,145 @@ + /* +* create_mask.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to make mask image (black and white). +* The program takes as input a source image and ouputs its corresponding +* mask image. +*/ + + + +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +Mat img0, img1, res1, final; + +Point point; +int drag = 0; + +int numpts = 100; +Point* pts = new Point[100]; + +int var = 0; +int flag = 0; +int flag1 = 0; + +int minx,miny,maxx,maxy,lenx,leny; + +int channel; + +void mouseHandler(int event, int x, int y, int, void*) +{ + + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i Date: Mon, 19 Aug 2013 13:16:04 +0530 Subject: [PATCH 07/27] added keyboard control --- modules/photo/include/opencv2/photo.hpp | 12 +- modules/photo/src/seamless_cloning.cpp | 43 ++- modules/photo/src/seamless_cloning.hpp | 122 +++---- modules/photo/test/test_cloning.cpp | 11 +- samples/cpp/cloning.cpp | 433 ++++++++++++++++++------ 5 files changed, 447 insertions(+), 174 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 673670354f..d825c2489e 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -63,7 +63,13 @@ enum { NORMAL_CLONE = 1, MIXED_CLONE = 2, - FEATURE_EXCHANGE = 3 + MONOCHROME_TRANSFER = 3 +}; + +enum +{ + RECURSIVE_FILTER = 1, + NC_FILTER = 2 }; //! restores the damaged image areas using one of the available intpainting algorithms @@ -303,7 +309,9 @@ CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray src, OutputArray dst); +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst); + +CV_EXPORTS_W void edgepreservefilter(InputArray _src, OutputArray _dst, int flags = 1, float sigma_h = 60, float sigma_r = 0.4); } // cv diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index c2d6c59b97..92beb02fe8 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -144,8 +144,12 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float float blue = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); - cvtColor(mask, gray, COLOR_BGR2GRAY); + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); int channel = 3; @@ -178,7 +182,11 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float beta = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); - cvtColor(mask, gray, COLOR_BGR2GRAY); + + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); @@ -200,14 +208,39 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, obj.illum_change(src,cs_mask,gray,blend,alpha,beta); } -void cv::textureFlattening(InputArray _src, OutputArray _dst) + +void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst) { Mat src = _src.getMat(); + Mat mask = _mask.getMat(); _dst.create(src.size(), src.type()); Mat blend = _dst.getMat(); - Cloning obj; - obj.texture_flatten(src,blend); + Mat gray = Mat::zeros(mask.size(),CV_8UC1); + + if(mask.channels() == 3) + cvtColor(mask, gray, COLOR_BGR2GRAY ); + else + gray = mask; + + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); + + int channel = 3; + for(int i=0;i(i,j) == 255) + { + for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); + } + } + + } + + Cloning obj; + obj.texture_flatten(src,cs_mask,gray,blend); } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 61fdad9c5e..a59cb5d16b 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -76,7 +76,7 @@ class Cloning void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue); void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &final); + void texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final); }; void Cloning::getGradientx( const Mat &img, Mat &gx) @@ -782,91 +782,79 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph } } -void Cloning::texture_flatten(Mat &I, Mat &final) + +void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final) { + init(I,wmask); - grx = Mat(I.size(),CV_32FC3); - gry = Mat(I.size(),CV_32FC3); + int w = I.size().width; + int h = I.size().height; - Mat out = Mat(I.size(),CV_8UC1); + getGradientx(I,grx); + getGradienty(I,gry); - getGradientx( I, grx); - getGradienty( I, gry); + getGradientx(mask,sgx); + getGradienty(mask,sgy); - Canny( I, out, 30, 45, 3 ); + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); - int channel = I.channels(); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); + erode(wmask, wmask, Kernel); - for(int i=0;i(i,j) != 255) { - grx.at(i,j*channel+c) = 0.0; - gry.at(i,j*channel+c) = 0.0; + sgx.at(i,j*channel+c) = 0.0; + sgy.at(i,j*channel+c) = 0.0; } } - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); - - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } - - Mat gxx = Mat(I.size(),CV_32FC3); - Mat gyy = Mat(I.size(),CV_32FC3); - - lapx(grx,gxx); - lapy(gry,gyy); - - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } - - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); - - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } - - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); - - clock_t tic = clock(); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (sgx.at(i,j*channel+c)*smask.at(i,j)); + sry32.at(i,j*channel+c) = + (sgy.at(i,j*channel+c)*smask.at(i,j)); + } + bitwise_not(wmask,wmask); - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); - clock_t toc = clock(); + for(int i=0;i < h; i++) + for(int j=0; j < w; j++) + for(int c=0;c(i,j*channel+c) = + (grx.at(i,j*channel+c)*smask1.at(i,j)); + gry32.at(i,j*channel+c) = + (gry.at(i,j*channel+c)*smask1.at(i,j)); + } - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); + calc(I,grx32,gry32,srx32,sry32); - for(int i=0;i(i,j*3+0) = resultr.at(i,j); final.at(i,j*3+1) = resultg.at(i,j); diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp index 583a069aee..bb62d874aa 100644 --- a/modules/photo/test/test_cloning.cpp +++ b/modules/photo/test/test_cloning.cpp @@ -164,14 +164,17 @@ TEST(Photo_SeamlessClone_illuminationChange, regression) TEST(Photo_SeamlessClone_textureFlattening, regression) { string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/"; - string original_path = folder + "source1.png"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; - Mat source = imread(original_path, IMREAD_COLOR); + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); - ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path; + ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1; + ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; Mat result; - textureFlattening(source, result); + textureFlattening(source, mask, result); imwrite(folder + "cloned.png", result); diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp index 70725d8e74..9a41ce229b 100644 --- a/samples/cpp/cloning.cpp +++ b/samples/cpp/cloning.cpp @@ -6,26 +6,31 @@ * * This tutorial demonstrates how to use OpenCV seamless cloning * module. -* Flags: -* 1- NORMAL_CLONE -* 2- MIXED_CLONE -* 3- FEATURE_EXCHANGE - -* The program takes as input a source and a destination image +* +* 1- Normal Cloning +* 2- Mixed Cloning +* 3- Monochrome Transfer +* 4- Color Change +* 5- Illumination change +* 6- Texture Flattening + +* The program takes as input a source and a destination image (for 1-3 methods) * and ouputs the cloned image. * Step 1: * -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button. -* -> To set the Polygon ROI, click the right mouse button. -* -> To reset the region selected, click the middle mouse button. +* -> To set the Polygon ROI, click the right mouse button or 'd' key. +* -> To reset the region selected, click the middle mouse button or 'r' key. * Step 2: * -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button. -* -> To get the cloned result, click the right mouse button. - +* -> To get the cloned result, click the right mouse button or 'c' key. +* -> To quit the program, use 'q' key. +* * Result: The cloned image will be displayed. */ +#include #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" @@ -47,6 +52,8 @@ Point* pts = new Point[100]; Point* pts2 = new Point[100]; Point* pts_diff = new Point[100]; +char src[50]; +char dest[50]; int var = 0; int flag = 0; @@ -57,6 +64,10 @@ int minxd,minyd,maxxd,maxyd,lenxd,lenyd; int channel,num; +float alpha,beta; + +float red, green, blue; + void source(int event, int x, int y, int, void*) { @@ -93,20 +104,20 @@ void source(int event, int x, int y, int, void*) pts[i] = point; if(var!=0) - { - const Point* pts3[1] = {&pts[0]}; - polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); - } + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } - for(int i=0;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) - { - cout << "Index out of range" << endl; - exit(0); - } + if(maxxd > im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) + { + cout << "Index out of range" << endl; + exit(0); + } - final1 = Mat::zeros(img2.size(),CV_8UC3); - res = Mat::zeros(img2.size(),CV_8UC1); - for(int i=miny, k=minyd;i<(miny+leny);i++,k++) - for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) - { - for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); + final1 = Mat::zeros(img2.size(),CV_8UC3); + res = Mat::zeros(img2.size(),CV_8UC1); + for(int i=miny, k=minyd;i<(miny+leny);i++,k++) + for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++) + { + for(int c=0;c(k,l*channel+c) = final.at(i,j*channel+c); - } - } + } + } - const Point* pts6[1] = {&pts2[0]}; - fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); + const Point* pts6[1] = {&pts2[0]}; + fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); - if(num == 1 || num == 2 || num == 3) - { + if(num == 1 || num == 2 || num == 3) + { seamlessClone(img0,img2,res1,point,blend,num); - imshow("Cloned Image", blend); + imshow("Cloned Image", blend); imwrite("cloned.png",blend); - waitKey(0); - } + waitKey(0); + } - for(int i = 0; i < flag ; i++) - { - pts2[i].x=0; - pts2[i].y=0; - } + for(int i = 0; i < flag ; i++) + { + pts2[i].x=0; + pts2[i].y=0; + } - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - } + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + } - im1.release(); + im1.release(); +} + +void checkfile(char *file) +{ + while(1) + { + printf("Enter %s Image: ",file); + if(!strcmp(file,"Source")) + { + cin >> src; + if(access( src, F_OK ) != -1 ) + { + break; + } + else + { + printf("Image doesn't exist\n"); + } + } + else if(!strcmp(file,"Destination")) + { + cin >> dest; + + if(access( dest, F_OK ) != -1 ) + { + break; + } + else + { + printf("Image doesn't exist\n"); + } + + } + } } int main(int argc, char **argv) { + cout << endl; + cout << "Cloning Module" << endl; + cout << "---------------" << endl; + cout << "Step 1:" << endl; + cout << " -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button." << endl; + cout << " -> To set the Polygon ROI, click the right mouse button or use 'd' key" << endl; + cout << " -> To reset the region selected, click the middle mouse button or use 'r' key." << endl; + + cout << "Step 2:" << endl; + cout << " -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button." << endl; + cout << " -> To get the cloned result, click the right mouse button or use 'c' key." << endl; + cout << " -> To quit the program, use 'q' key." << endl; + cout << endl; + cout << "Options: " << endl; + cout << endl; + cout << "1) Normal Cloning " << endl; + cout << "2) Mixed Cloning " << endl; + cout << "3) Monochrome Transfer " << endl; + cout << "4) Local Color Change " << endl; + cout << "5) Local Illumination Change " << endl; + cout << "6) Texture Flattening " << endl; + + cout << endl; + + cout << "Press number 1-6 to choose from above techniques: "; + cin >> num; + cout << endl; + + char s[]="Source"; + char d[]="Destination"; + + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - if (argc != 3) + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + + if(num == 1 || num == 2 || num == 3) { - cout << "usage: " << argv[0] << " " << " " << endl; - exit(1); + + checkfile(s); + checkfile(d); + + img0 = imread(src); + + img2 = imread(dest); + + channel = img0.channels(); + + res = Mat::zeros(img2.size(),CV_8UC1); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + final1 = Mat::zeros(img2.size(),CV_8UC3); + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + /////////// destination image /////////////// + + namedWindow("Destination", 1); + setMouseCallback("Destination", destination, NULL); + imshow("Destination",img2); + } + else if(num == 4) + { + checkfile(s); - Mat src = imread(argv[1]); - Mat dest = imread(argv[2]); + cout << "Enter RGB values: " << endl; + cout << "Red: "; + cin >> red; - cout << "Flags:" << endl; - cout << "1- NORMAL_CLONE" << endl; - cout << "2- MIXED_CLONE" << endl; - cout << "3- FEATURE_EXCHANGE" << endl << endl; + cout << "Green: "; + cin >> green; - cout << "Enter Flag:"; - cin >> num; + cout << "Blue: "; + cin >> blue; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + img0 = imread(src); + + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - img0 = src; - img2 = dest; + } + else if(num == 5) + { + checkfile(s); + + cout << "alpha: "; + cin >> alpha; + + cout << "beta: "; + cin >> beta; + + img0 = imread(src); - channel = img0.channels(); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); - res = Mat::zeros(img2.size(),CV_8UC1); - res1 = Mat::zeros(img0.size(),CV_8UC1); - final = Mat::zeros(img0.size(),CV_8UC3); - final1 = Mat::zeros(img2.size(),CV_8UC3); - //////////// source image /////////////////// + //////////// source image /////////////////// - namedWindow("Source", 1); - setMouseCallback("Source", source, NULL); - imshow("Source", img0); + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + + + } + else if(num == 6) + { + checkfile(s); - /////////// destination image /////////////// + img0 = imread(src); - namedWindow("Destination", 1); - setMouseCallback("Destination", destination, NULL); - imshow("Destination",img2); - waitKey(0); + res1 = Mat::zeros(img0.size(),CV_8UC1); + final = Mat::zeros(img0.size(),CV_8UC3); + + //////////// source image /////////////////// + + namedWindow("Source", 1); + setMouseCallback("Source", source, NULL); + imshow("Source", img0); + } + + while(true) + { + char key = waitKey(0); + + if(key == 'd') + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i Date: Tue, 27 Aug 2013 13:38:38 +0530 Subject: [PATCH 08/27] edge preserve filters added and windows warning removed update1 --- modules/photo/src/npr.cpp | 34 +++ modules/photo/src/npr.hpp | 490 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 524 insertions(+) create mode 100644 modules/photo/src/npr.cpp create mode 100644 modules/photo/src/npr.hpp diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp new file mode 100644 index 0000000000..c2311c8122 --- /dev/null +++ b/modules/photo/src/npr.cpp @@ -0,0 +1,34 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include +#include + +#include "npr.hpp" + +using namespace std; +using namespace cv; + +void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); + + int h = I.size().height; + int w = I.size().width; + + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); + + Domain_Filter obj; + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + obj.filter(img, res, sigma_s, sigma_r, flags); + + convertScaleAbs(res, dst, 255,0); +} diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp new file mode 100644 index 0000000000..856a4768b6 --- /dev/null +++ b/modules/photo/src/npr.hpp @@ -0,0 +1,490 @@ +#include "precomp.hpp" +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include +#include +#include +#include "math.h" + +using namespace std; +using namespace cv; + +double myinf = std::numeric_limits::infinity(); + +class Domain_Filter +{ + public: + Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx; + void init(const Mat &img, int flags, float sigma_s, float sigma_r); + void getGradientx( const Mat &img, Mat &gx); + void getGradienty( const Mat &img, Mat &gy); + void diffx(const Mat &img, Mat &temp); + void diffy(const Mat &img, Mat &temp); + void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); + void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); + void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); + void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags); +}; + +void Domain_Filter::diffx(const Mat &img, Mat &temp) +{ + int channel = img.channels(); + + for(int i = 0; i < img.size().height; i++) + for(int j = 0; j < img.size().width-1; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } + } +} + +void Domain_Filter::diffy(const Mat &img, Mat &temp) +{ + int channel = img.channels(); + + for(int i = 0; i < img.size().height-1; i++) + for(int j = 0; j < img.size().width; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at((i+1),j*channel+c) - img.at(i,j*channel+c); + } + } +} + +void Domain_Filter::getGradientx( const Mat &img, Mat &gx) +{ + int w = img.cols; + int h = img.rows; + int channel = img.channels(); + + for(int i=0;i(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } +} +void Domain_Filter::getGradienty( const Mat &img, Mat &gy) +{ + int w = img.cols; + int h = img.rows; + int channel = img.channels(); + + for(int i=0;i(i,j*channel+c) = + img.at(i+1,j*channel+c) - img.at(i,j*channel+c); + + } +} + +void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) +{ + + float a; + + int h = output.rows; + int w = output.cols; + int channel = output.channels(); + + a = exp(-sqrt(2) / sigma_h); + + Mat temp = Mat(h,w,CV_32FC3); + + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); + + + Mat V = Mat(h,w,CV_32FC1); + + for(int i=0;i(i,j) = pow(a,hz.at(i,j)); + + + for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); + } + } + } + + for(int i=0; i= 0; j--) + { + for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); + } + } + } + + + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = temp.at(i,j*channel+c); + + temp.release(); + V.release(); + + +} + +void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius) +{ + int h = output.rows; + int w = output.cols; + Mat lower_pos = Mat(h,w,CV_32FC1); + Mat upper_pos = Mat(h,w,CV_32FC1); + + for(int i=0;i(i,j) = hz.at(i,j) - radius; + upper_pos.at(i,j) = hz.at(i,j) + radius; + } + + lower_idx = Mat::zeros(h,w,CV_32FC1); + upper_idx = Mat::zeros(h,w,CV_32FC1); + + Mat domain_row = Mat::zeros(1,w+1,CV_32FC1); + + for(int i=0;i(0,j) = hz.at(i,j); + domain_row.at(0,w) = myinf; + + Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); + Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); + + for(int j=0;j(0,j) = lower_pos.at(i,j); + upper_pos_row.at(0,j) = upper_pos.at(i,j); + } + + Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1); + Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1); + + for(int j=0;j(0,j) > lower_pos_row.at(0,0)) + { + temp_lower_idx.at(0,0) = j; + break; + } + } + for(int j=0;j(0,j) > upper_pos_row.at(0,0)) + { + temp_upper_idx.at(0,0) = j; + break; + } + } + + int temp = 0; + for(int j=1;j(0,j-1);k(0,k) > lower_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } + + temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; + + count = 0; + for(int k=temp_upper_idx.at(0,j-1);k(0,k) > upper_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } + + temp_upper_idx.at(0,j) = temp_upper_idx.at(0,j-1) + temp; + } + + for(int j=0;j(i,j) = temp_lower_idx.at(0,j) + 1; + upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; + } + + + lower_pos_row.release(); + upper_pos_row.release(); + temp_lower_idx.release(); + temp_upper_idx.release(); + } + for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); + +} +void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius) +{ + + int h = output.rows; + int w = output.cols; + int channel = output.channels(); + + compute_boxfilter(output,hz,psketch,radius); + + Mat box_filter = Mat::zeros(h,w+1,CV_32FC3); + + for(int i = 0; i < h; i++) + { + box_filter.at(i,1*channel+0) = output.at(i,0*channel+0); + box_filter.at(i,1*channel+1) = output.at(i,0*channel+1); + box_filter.at(i,1*channel+2) = output.at(i,0*channel+2); + for(int j = 2; j < w+1; j++) + { + for(int c=0;c(i,j*channel+c) = output.at(i,(j-1)*channel+c) + box_filter.at(i,(j-1)*channel+c); + } + } + + Mat indices = Mat::zeros(h,w,CV_32FC1); + Mat final = Mat::zeros(h,w,CV_32FC3); + + for(int i=0;i(i,j) = i+1; + + Mat a = Mat::zeros(h,w,CV_32FC1); + Mat b = Mat::zeros(h,w,CV_32FC1); + + for(int c=0;c(i,j) = (c+1)*flag.at(i,j); + + for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); + b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); + + } + + int p,q,r,rem; + int p1,q1,r1,rem1; + + for(int i=0;i(i,j)/(h*(w+1)); + rem = b.at(i,j) - r*h*(w+1); + q = rem/h; + p = rem - q*h; + if(q==0) + { + p=h; + q=w; + r=r-1; + } + if(p==0) + { + p=h; + q=q-1; + } + + + r1 = a.at(i,j)/(h*(w+1)); + rem1 = a.at(i,j) - r1*h*(w+1); + q1 = rem1/h; + p1 = rem1 - q1*h; + if(p1==0) + { + p1=h; + q1=q1-1; + } + + + final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) + /(upper_idx.at(i,j) - lower_idx.at(i,j)); + } + } + } + + for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); + + +} +void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r) +{ + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); + + //////////////////////////////////// horizontal and vertical partial derivatives ///////////////////////////////// + + Mat derivx = Mat::zeros(h,w-1,CV_32FC3); + Mat derivy = Mat::zeros(h-1,w,CV_32FC3); + + diffx(img,derivx); + diffy(img,derivy); + + Mat distx = Mat::zeros(h,w,CV_32FC1); + Mat disty = Mat::zeros(h,w,CV_32FC1); + + //////////////////////// Compute the l1-norm distance of neighbor pixels //////////////////////////////////////////////// + + for(int i = 0; i < h; i++) + for(int j = 0,k=1; j < w-1; j++,k++) + for(int c = 0; c < channel; c++) + { + distx.at(i,k) = + distx.at(i,k) + abs(derivx.at(i,j*channel+c)); + } + + for(int i = 0,k=1; i < h-1; i++,k++) + for(int j = 0; j < w; j++) + for(int c = 0; c < channel; c++) + { + disty.at(k,j) = + disty.at(k,j) + abs(derivy.at(i,j*channel+c)); + } + + ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. ///////////////////////////// + + horiz = Mat(h,w,CV_32FC1); + vert = Mat(h,w,CV_32FC1); + + Mat final = Mat(h,w,CV_32FC3); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); + vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); + } + + + O = Mat(h,w,CV_32FC3); + + for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); + + O_t = Mat(w,h,CV_32FC3); + + if(flags == 2) + { + + ct_H = Mat(h,w,CV_32FC1); + ct_V = Mat(h,w,CV_32FC1); + + for(int i = 0; i < h; i++) + { + ct_H.at(i,0) = horiz.at(i,0); + for(int j = 1; j < w; j++) + { + ct_H.at(i,j) = horiz.at(i,j) + ct_H.at(i,j-1); + } + } + + for(int j = 0; j < w; j++) + { + ct_V.at(0,j) = vert.at(0,j); + for(int i = 1; i < h; i++) + { + ct_V.at(i,j) = vert.at(i,j) + ct_V.at(i-1,j); + } + } + } + +} +void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1) +{ + int no_of_iter = 3; + int h = img.size().height; + int w = img.size().width; + float sigma_h = sigma_s; + + init(img,flags,sigma_s,sigma_r); + + if(flags == 1) + { + + Mat vert_t = vert.t(); + + for(int i=0;i Date: Tue, 3 Sep 2013 21:12:05 +0530 Subject: [PATCH 09/27] new filters added and all the 3 modules updated All 3 modules Updated --- modules/photo/doc/cloning.rst | 27 +- modules/photo/doc/npr.rst | 90 +++ modules/photo/include/opencv2/photo.hpp | 34 +- modules/photo/src/contrast_preserve.cpp | 274 ++++--- modules/photo/src/contrast_preserve.hpp | 30 +- modules/photo/src/npr.cpp | 236 +++++- modules/photo/src/npr.hpp | 953 ++++++++++++++---------- modules/photo/src/seamless_cloning.cpp | 58 +- modules/photo/src/seamless_cloning.hpp | 30 +- modules/photo/test/test_cloning.cpp | 4 +- modules/photo/test/test_npr.cpp | 146 ++++ samples/cpp/cloning.cpp | 42 +- samples/cpp/cloning_example.cpp | 243 ++++++ samples/cpp/npr_demo.cpp | 107 +++ 14 files changed, 1652 insertions(+), 622 deletions(-) create mode 100644 modules/photo/doc/npr.rst create mode 100644 modules/photo/test/test_npr.cpp create mode 100644 samples/cpp/cloning_example.cpp create mode 100644 samples/cpp/npr_demo.cpp diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 740e1ab64b..11e9bce135 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -39,19 +39,21 @@ colorChange ----------- Given an original color image, two differently colored versions of this image can be mixed seamlessly. -.. ocv:function:: void colorChange( InputArray src, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0) +.. ocv:function:: void colorChange( InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, float green_mul = 1.0, float blue_mul = 1.0) :param src: Input 8-bit 3-channel image. + :param mask: Input 8-bit 1 or 3-channel image. + :param dst: Output image with the same size and type as ``src`` . - :param red: R-channel Value + :param red_mul: R-channel multiply factor. - :param green: G-channel Value + :param green_mul: G-channel multiply factor. - :param blue: B-channel Value + :param blue_mul: B-channel multiply factor. -RGB values between .5 to 2.5 +Multiplication factor is between .5 to 2.5. illuminationChange @@ -59,10 +61,12 @@ illuminationChange Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson solver, modifies locally the apparent illumination of an image. -.. ocv:function:: void illuminationChange(InputArray src, OutputArray dst, float alpha = 0.2, float beta = 0.4) +.. ocv:function:: void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4) :param src: Input 8-bit 3-channel image. + :param mask: Input 8-bit 1 or 3-channel image. + :param dst: Output image with the same size and type as ``src``. :param alpha: Value ranges between 0-2. @@ -74,14 +78,21 @@ This is useful to highlight under-exposed foreground objects or to reduce specul textureFlattening ----------------- By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected -region, giving its contents a flat aspect. +region, giving its contents a flat aspect. Here Canny Edge Detector is used. -.. ocv:function:: void textureFlattening(InputArray src, OutputArray dst) +.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold, double high_threshold, int kernel_size) :param src: Input 8-bit 3-channel image. + :param mask: Input 8-bit 1 or 3-channel image. + :param dst: Output image with the same size and type as ``src``. + :param low_threshold: Range from 0 to 100. + + :param high_threshold: Value > 100. + + :param kernel_size: The size of the Sobel kernel to be used. **NOTE:** diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst new file mode 100644 index 0000000000..db56c6955c --- /dev/null +++ b/modules/photo/doc/npr.rst @@ -0,0 +1,90 @@ +Non-Photorealistic Rendering +============================ + +.. highlight:: cpp + +edgePreservingFilter +-------------------- + +Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications. + +.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output 8-bit 3-channel image. + + :param flags: Edge preserving filters: + + * **RECURS_FILTER** + + * **NORMCONV_FILTER** + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + +detailEnhance +------------- +This filter enhances the details of a particular image. + +.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + +pencilSketch +------------ +Pencil-like non-photorealistic line drawing + +.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + + :param src: Input 8-bit 3-channel image. + + :param dst1: Output 8-bit 1-channel image. + + :param dst2: Output image with the same size and type as ``src``. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + :param shade_factor: Range between 0 to 0.1. + + +stylization +----------- +Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features. + +.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src``. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + + +edgeEnhance +----------- +Able to suppress low-amplitude details and enhance edges. + +.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); + + :param src: Input 8-bit 3-channel image. + + :param dst: Output 8-bit 1-channel image. + + :param sigma_s: Range between 0 to 200. + + :param sigma_r: Range between 0 to 1. + diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index d825c2489e..1eb5ccaab1 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -68,8 +68,8 @@ enum enum { - RECURSIVE_FILTER = 1, - NC_FILTER = 2 + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 }; //! restores the damaged image areas using one of the available intpainting algorithms @@ -301,17 +301,35 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); -CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, InputArray mask, Point p, OutputArray _blend, int flags); +CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray _blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, + float green_mul = 1.0, float blue_mul = 1.0); -CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4); +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst); +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + double low_threshold, double high_threshold, + int kernel_size); -CV_EXPORTS_W void edgepreservefilter(InputArray _src, OutputArray _dst, int flags = 1, float sigma_h = 60, float sigma_r = 0.4); +CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4); + +CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15); + +CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst, OutputArray dst1, + float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + +CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); + +CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 9a659691a8..14ed6ac30f 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -57,7 +57,7 @@ double norm(double); double norm(double E) { - return (sqrt(pow(E,2))); + return (sqrt(pow(E,2))); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) @@ -71,170 +71,168 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) if(!I.data ) { - cout << "Could not open or find the image" << endl ; - return; - } - if(I.channels() !=3) - { - cout << "Input Color Image" << endl; - return; - } - - int maxIter = 15; - int iterCount = 0; + cout << "Could not open or find the image" << endl ; + return; + } + if(I.channels() !=3) + { + cout << "Input Color Image" << endl; + return; + } + + int maxIter = 15; + int iterCount = 0; float tol = .0001; double E = 0; double pre_E = std::numeric_limits::infinity(); - Decolor obj; + Decolor obj; - Mat img; + Mat img; img = Mat(I.size(),CV_32FC3); I.convertTo(img,CV_32FC3,1.0/255.0); obj.init(); - vector Cg; - vector < vector > polyGrad; - vector < vector > bc; - vector < vector < int > > comb; + vector Cg; + vector < vector > polyGrad; + vector < vector > bc; + vector < vector < int > > comb; - vector alf; + vector alf; - obj.grad_system(img,polyGrad,Cg,comb); - obj.weak_order(img,alf); + obj.grad_system(img,polyGrad,Cg,comb); + obj.weak_order(img,alf); - Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); - obj.wei_update_matrix(polyGrad,Cg,Mt); + Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); + obj.wei_update_matrix(polyGrad,Cg,Mt); - vector wei; - obj.wei_inti(comb,wei); + vector wei; + obj.wei_inti(comb,wei); - //////////////////////////////// main loop starting //////////////////////////////////////// + //////////////////////////////// main loop starting //////////////////////////////////////// - while(norm(E-pre_E) > tol) - { - iterCount +=1; + while(norm(E-pre_E) > tol) + { + iterCount +=1; pre_E = E; - vector G_pos; - vector G_neg; - - vector temp; - vector temp1; - - double val = 0.0; - for(unsigned int i=0;i< polyGrad[0].size();i++) - { - val = 0.0; - for(unsigned int j =0;j EXPsum; - vector EXPterm; - - for(unsigned int i = 0;i temp2; - - for(unsigned int i=0;i wei1; - - for(unsigned int i=0;i< polyGrad.size();i++) - { - val1 = 0.0; - for(unsigned int j =0;j(i,j) * EXPterm[j]); - } - wei1.push_back(val1); - } - - for(unsigned int i =0;i G_pos; + vector G_neg; + + vector temp; + vector temp1; + + double val = 0.0; + for(unsigned int i=0;i< polyGrad[0].size();i++) + { + val = 0.0; + for(unsigned int j =0;j EXPsum; + vector EXPterm; + + for(unsigned int i = 0;i temp2; + + for(unsigned int i=0;i wei1; + + for(unsigned int i=0;i< polyGrad.size();i++) + { + val1 = 0.0; + for(unsigned int j =0;j(i,j) * EXPterm[j]); + } + wei1.push_back(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(); - } + 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); - obj.grayImContruct(wei, img, Gray); + Mat Gray = Mat::zeros(img.size(),CV_32FC1); + obj.grayImContruct(wei, img, Gray); - Gray.convertTo(dst,CV_8UC1,255); + Gray.convertTo(dst,CV_8UC1,255); /////////////////////////////////// Contrast Boosting ///////////////////////////////// - - Mat lab = Mat(img.size(),CV_8UC3); - Mat color = Mat(img.size(),CV_8UC3); - Mat l = Mat(img.size(),CV_8UC1); - Mat a = Mat(img.size(),CV_8UC1); - Mat b = Mat(img.size(),CV_8UC1); - - cvtColor(I,lab,COLOR_BGR2Lab); - - int h1 = img.size().height; - int w1 = img.size().width; - - for(int i =0;i(i,j) = lab.at(i,j*3+0); - a.at(i,j) = lab.at(i,j*3+1); - b.at(i,j) = lab.at(i,j*3+2); - } - - for(int i =0;i(i,j) = 255.0*Gray.at(i,j); - } - - for(int i =0;i(i,j*3+0) = l.at(i,j); - lab.at(i,j*3+1) = a.at(i,j); - lab.at(i,j*3+2) = b.at(i,j); - } - - cvtColor(lab,color_boost,COLOR_Lab2BGR); + + Mat lab = Mat(img.size(),CV_8UC3); + Mat color = Mat(img.size(),CV_8UC3); + Mat l = Mat(img.size(),CV_8UC1); + Mat a = Mat(img.size(),CV_8UC1); + Mat b = Mat(img.size(),CV_8UC1); + + cvtColor(I,lab,COLOR_BGR2Lab); + + int h1 = img.size().height; + int w1 = img.size().width; + + for(int i =0;i(i,j) = lab.at(i,j*3+0); + a.at(i,j) = lab.at(i,j*3+1); + b.at(i,j) = lab.at(i,j*3+2); + } + + for(int i =0;i(i,j) = 255.0*Gray.at(i,j); + } + + for(int i =0;i(i,j*3+0) = l.at(i,j); + lab.at(i,j*3+1) = a.at(i,j); + lab.at(i,j*3+2) = b.at(i,j); + } + + cvtColor(lab,color_boost,COLOR_Lab2BGR); } diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 607b494832..c9d75036c2 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -39,7 +39,6 @@ // //M*/ - #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -69,7 +68,7 @@ class Decolor void add_to_vector_poly(vector < vector > &polyGrad, vector &curGrad); void weak_order(Mat img, vector &alf); void grad_system(Mat img, vector < vector < double > > &polyGrad, - vector < double > &Cg, vector < vector >& comb); + vector < double > &Cg, vector < vector >& comb); void wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X); void wei_inti(vector < vector > &comb, vector &wei); void grayImContruct(vector &wei, Mat img, Mat &Gray); @@ -87,7 +86,6 @@ float sigma = .02; double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) { vector P; - vector temp; vector temp1; @@ -112,8 +110,6 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } - - void Decolor::init() { kernel = Mat(1,2, CV_32FC1); @@ -123,7 +119,6 @@ void Decolor::init() kernel1.at(0,0)=1.0; kernel1.at(1,0)=-1.0; order = 2; - } vector Decolor::product(vector < vector > &comb, vector &initRGB) @@ -183,7 +178,7 @@ void Decolor::gradvector(const Mat &img, vector &grad) dest.release(); dest1.release(); } - + void Decolor::colorGrad(Mat img, vector &Cg) { @@ -222,7 +217,6 @@ void Decolor::colorGrad(Mat img, vector &Cg) ImL.clear(); Ima.clear(); Imb.clear(); - } void Decolor::add_vector(vector < vector > &comb, int r,int g,int b) @@ -267,7 +261,7 @@ void Decolor::weak_order(Mat img, vector &alf) green.at(i,j) = img.at(i,j*3+1); blue.at(i,j) = img.at(i,j*3+0); } - + vector Rg; vector Gg; vector Bg; @@ -275,7 +269,7 @@ void Decolor::weak_order(Mat img, vector &alf) vector t1; vector t2; vector t3; - + vector tmp1; vector tmp2; vector tmp3; @@ -333,7 +327,7 @@ void Decolor::weak_order(Mat img, vector &alf) for(unsigned int i =0 ;i < Rg.size();i++) alf[i] -= tmp1[i] * tmp2[i] * tmp3[i]; - + double sum =0.0; for(unsigned int i=0;i &alf) } void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, - vector < double > &Cg, vector < vector >& comb) + vector < double > &Cg, vector < vector >& comb) { int h = img.size().height; int w = img.size().width; - double sizefactor; if((h + w) > 800) { @@ -375,7 +368,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, h = img.size().height; w = img.size().width; colorGrad(img,Cg); - + Mat curIm = Mat(img.size(),CV_32FC1); Mat red = Mat(img.size(),CV_32FC1); Mat green = Mat(img.size(),CV_32FC1); @@ -400,7 +393,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, for(int j=0;j(i,j)= pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + pow(blue.at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); @@ -468,7 +461,6 @@ void Decolor::wei_inti(vector < vector > &comb, vector &wei) void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) { - int h=img.size().height; int w=img.size().width; @@ -485,7 +477,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) } int kk =0; - + for(int r =0;r<=order;r++) for(int g=0;g<=order;g++) for(int b=0;b<=order;b++) @@ -495,7 +487,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int j=0;j(i,j)=Gray.at(i,j) + wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + pow(blue.at(i,j),b); kk=kk+1; } @@ -508,7 +500,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) { if(Gray.at(i,j) < minval) minval = Gray.at(i,j); - + if(Gray.at(i,j) > maxval) maxval = Gray.at(i,j); } diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index c2311c8122..54f5ce55ed 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -1,3 +1,44 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/highgui.hpp" @@ -11,7 +52,7 @@ using namespace std; using namespace cv; -void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) +void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) { Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC3); @@ -32,3 +73,196 @@ void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float convertScaleAbs(res, dst, 255,0); } + +void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); + + int h = I.size().height; + int w = I.size().width; + int channel = I.channels(); + float factor = 3.0; + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); + + Mat result = Mat(img.size(),CV_32FC3); + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); + + cvtColor(img,lab,COLOR_BGR2Lab); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + l_channel.at(i,j) = lab.at(i,j*channel+0); + a_channel.at(i,j) = lab.at(i,j*channel+1); + b_channel.at(i,j) = lab.at(i,j*channel+2); + } + + Mat L = Mat(img.size(),CV_32FC1); + + l_channel.convertTo(L,CV_32FC1,1.0/255.0); + + Domain_Filter obj; + + obj.filter(L, res, sigma_s, sigma_r, 1); + + Mat detail = Mat(h,w,CV_32FC1); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + detail.at(i,j) = L.at(i,j) - res.at(i,j); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); + + L.convertTo(l_channel,CV_32FC1,255); + + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + lab.at(i,j*channel+0) = l_channel.at(i,j); + lab.at(i,j*channel+1) = a_channel.at(i,j); + lab.at(i,j*channel+2) = b_channel.at(i,j); + } + + cvtColor(lab,result,COLOR_Lab2BGR); + result.convertTo(dst,CV_8UC3,255); +} + +void cv::pencilSketch(InputArray _src, OutputArray _dst, OutputArray _dst1, float sigma_s, float sigma_r, float shade_factor) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); + + _dst1.create(I.size(), CV_8UC3); + Mat dst1 = _dst1.getMat(); + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + Domain_Filter obj; + + Mat sketch = Mat(I.size(),CV_32FC1); + Mat color_sketch = Mat(I.size(),CV_32FC3); + + obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor); + + sketch.convertTo(dst,CV_8UC1,255); + color_sketch.convertTo(dst1,CV_8UC3,255); + +} + +void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); + + Mat res = Mat(h,w,CV_32FC3); + + Domain_Filter obj; + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + + vector planes; + split(res, planes); + + Mat magXR = Mat(h, w, CV_32FC1); + Mat magYR = Mat(h, w, CV_32FC1); + + Mat magXG = Mat(h, w, CV_32FC1); + Mat magYG = Mat(h, w, CV_32FC1); + + Mat magXB = Mat(h, w, CV_32FC1); + Mat magYB = Mat(h, w, CV_32FC1); + + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); + + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); + + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); + + Mat magx = Mat(h,w,CV_32FC1); + Mat magy = Mat(h,w,CV_32FC1); + + Mat mag1 = Mat(h,w,CV_32FC1); + Mat mag2 = Mat(h,w,CV_32FC1); + Mat mag3 = Mat(h,w,CV_32FC1); + + magnitude(magXR,magYR,mag1); + magnitude(magXG,magYG,mag2); + magnitude(magXB,magYB,mag3); + + Mat magnitude = Mat(h,w,CV_32FC1); + + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); + } + + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = 1.0 - magnitude.at(i,j); + } + + Mat stylized = Mat(h,w,CV_32FC3); + + for(int i =0;i < h;i++) + for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); + } + + stylized.convertTo(dst,CV_8UC3,255); +} + +void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) +{ + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); + + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); + + Mat orig = img.clone(); + + int h = img.size().height; + int w = img.size().width; + + Mat res = Mat(h,w,CV_32FC3); + Mat magnitude = Mat(h,w,CV_32FC1); + + Mat mag8 = Mat(h,w,CV_32FC1); + + Domain_Filter obj; + + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + + obj.find_magnitude(res,magnitude); + + magnitude.convertTo(dst,CV_8UC1,255); +} diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 856a4768b6..66638ccbd8 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -1,3 +1,44 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -13,478 +54,616 @@ double myinf = std::numeric_limits::infinity(); class Domain_Filter { - public: - Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx; - void init(const Mat &img, int flags, float sigma_s, float sigma_r); - void getGradientx( const Mat &img, Mat &gx); - void getGradienty( const Mat &img, Mat &gy); - void diffx(const Mat &img, Mat &temp); - void diffy(const Mat &img, Mat &temp); - void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); - void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); - void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); - void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags); + public: + Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx; + void init(const Mat &img, int flags, float sigma_s, float sigma_r); + void getGradientx( const Mat &img, Mat &gx); + void getGradienty( const Mat &img, Mat &gy); + void diffx(const Mat &img, Mat &temp); + void diffy(const Mat &img, Mat &temp); + void find_magnitude(Mat &img, Mat &mag); + void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); + void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); + void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); + void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags); + void pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor); + void Depth_of_field(const Mat &img, Mat &img1, float sigma_s, float sigma_r); }; void Domain_Filter::diffx(const Mat &img, Mat &temp) { - int channel = img.channels(); - - for(int i = 0; i < img.size().height; i++) - for(int j = 0; j < img.size().width-1; j++) - { - for(int c =0; c < channel; c++) - { - temp.at(i,j*channel+c) = - img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); - } - } + int channel = img.channels(); + + for(int i = 0; i < img.size().height; i++) + for(int j = 0; j < img.size().width-1; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } + } } void Domain_Filter::diffy(const Mat &img, Mat &temp) { - int channel = img.channels(); - - for(int i = 0; i < img.size().height-1; i++) - for(int j = 0; j < img.size().width; j++) - { - for(int c =0; c < channel; c++) - { - temp.at(i,j*channel+c) = - img.at((i+1),j*channel+c) - img.at(i,j*channel+c); - } - } + int channel = img.channels(); + + for(int i = 0; i < img.size().height-1; i++) + for(int j = 0; j < img.size().width; j++) + { + for(int c =0; c < channel; c++) + { + temp.at(i,j*channel+c) = + img.at((i+1),j*channel+c) - img.at(i,j*channel+c); + } + } } void Domain_Filter::getGradientx( const Mat &img, Mat &gx) { - int w = img.cols; - int h = img.rows; - int channel = img.channels(); - - for(int i=0;i(i,j*channel+c) = - img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); - } + int w = img.cols; + int h = img.rows; + int channel = img.channels(); + + for(int i=0;i(i,j*channel+c) = + img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); + } } + void Domain_Filter::getGradienty( const Mat &img, Mat &gy) { - int w = img.cols; - int h = img.rows; - int channel = img.channels(); - - for(int i=0;i(i,j*channel+c) = - img.at(i+1,j*channel+c) - img.at(i,j*channel+c); - - } + int w = img.cols; + int h = img.rows; + int channel = img.channels(); + + for(int i=0;i(i,j*channel+c) = + img.at(i+1,j*channel+c) - img.at(i,j*channel+c); + + } } -void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) +void Domain_Filter::find_magnitude(Mat &img, Mat &mag) { - float a; + int h = img.rows; + int w = img.cols; + + vector planes; + split(img, planes); + + Mat magXR = Mat(h, w, CV_32FC1); + Mat magYR = Mat(h, w, CV_32FC1); + + Mat magXG = Mat(h, w, CV_32FC1); + Mat magYG = Mat(h, w, CV_32FC1); + + Mat magXB = Mat(h, w, CV_32FC1); + Mat magYB = Mat(h, w, CV_32FC1); + + getGradientx(planes[0], magXR); + getGradienty(planes[0], magYR); + + getGradientx(planes[1], magXG); + getGradienty(planes[1], magYG); + + getGradientx(planes[2], magXR); + getGradienty(planes[2], magYR); + + Mat magx = Mat(h,w,CV_32FC1); + Mat magy = Mat(h,w,CV_32FC1); + + Mat mag1 = Mat(h,w,CV_32FC1); + Mat mag2 = Mat(h,w,CV_32FC1); + Mat mag3 = Mat(h,w,CV_32FC1); + + magnitude(magXR,magYR,mag1); + magnitude(magXG,magYG,mag2); + magnitude(magXB,magYB,mag3); - int h = output.rows; - int w = output.cols; - int channel = output.channels(); + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); + } - a = exp(-sqrt(2) / sigma_h); - Mat temp = Mat(h,w,CV_32FC3); + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = 1.0 - mag.at(i,j); + } - for(int i =0; i < h;i++) - for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); +} + +void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) +{ + + float a; + + int h = output.rows; + int w = output.cols; + int channel = output.channels(); + + a = exp(-sqrt(2) / sigma_h); + Mat temp = Mat(h,w,CV_32FC3); - Mat V = Mat(h,w,CV_32FC1); + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); - for(int i=0;i(i,j) = pow(a,hz.at(i,j)); + Mat V = Mat(h,w,CV_32FC1); - for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); - } - } - } - - for(int i=0; i= 0; j--) - { - for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); - } - } - } + for(int i=0;i(i,j) = pow(a,hz.at(i,j)); - for(int i =0; i < h;i++) - for(int j=0;j(i,j*channel+c) = temp.at(i,j*channel+c); + for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); + } + } + } - temp.release(); - V.release(); + for(int i=0; i= 0; j--) + { + for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + + (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); + } + } + } + for(int i =0; i < h;i++) + for(int j=0;j(i,j*channel+c) = temp.at(i,j*channel+c); + + temp.release(); + V.release(); } void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius) { - int h = output.rows; - int w = output.cols; - Mat lower_pos = Mat(h,w,CV_32FC1); - Mat upper_pos = Mat(h,w,CV_32FC1); - - for(int i=0;i(i,j) = hz.at(i,j) - radius; - upper_pos.at(i,j) = hz.at(i,j) + radius; - } - - lower_idx = Mat::zeros(h,w,CV_32FC1); - upper_idx = Mat::zeros(h,w,CV_32FC1); - - Mat domain_row = Mat::zeros(1,w+1,CV_32FC1); - - for(int i=0;i(0,j) = hz.at(i,j); - domain_row.at(0,w) = myinf; - - Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); - Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); - - for(int j=0;j(0,j) = lower_pos.at(i,j); - upper_pos_row.at(0,j) = upper_pos.at(i,j); - } - - Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1); - Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1); - - for(int j=0;j(0,j) > lower_pos_row.at(0,0)) - { - temp_lower_idx.at(0,0) = j; - break; - } - } - for(int j=0;j(0,j) > upper_pos_row.at(0,0)) - { - temp_upper_idx.at(0,0) = j; - break; - } - } - - int temp = 0; - for(int j=1;j(0,j-1);k(0,k) > lower_pos_row.at(0,j)) - { - temp = count; - break; - } - count++; - } - - temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; - - count = 0; - for(int k=temp_upper_idx.at(0,j-1);k(0,k) > upper_pos_row.at(0,j)) - { - temp = count; - break; - } - count++; - } - - temp_upper_idx.at(0,j) = temp_upper_idx.at(0,j-1) + temp; - } - - for(int j=0;j(i,j) = temp_lower_idx.at(0,j) + 1; - upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; - } - - - lower_pos_row.release(); - upper_pos_row.release(); - temp_lower_idx.release(); - temp_upper_idx.release(); - } - for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); + int h = output.rows; + int w = output.cols; + Mat lower_pos = Mat(h,w,CV_32FC1); + Mat upper_pos = Mat(h,w,CV_32FC1); + + for(int i=0;i(i,j) = hz.at(i,j) - radius; + upper_pos.at(i,j) = hz.at(i,j) + radius; + } + + lower_idx = Mat::zeros(h,w,CV_32FC1); + upper_idx = Mat::zeros(h,w,CV_32FC1); + + Mat domain_row = Mat::zeros(1,w+1,CV_32FC1); + + for(int i=0;i(0,j) = hz.at(i,j); + domain_row.at(0,w) = myinf; + + Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); + Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); + + for(int j=0;j(0,j) = lower_pos.at(i,j); + upper_pos_row.at(0,j) = upper_pos.at(i,j); + } + + Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1); + Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1); + + for(int j=0;j(0,j) > lower_pos_row.at(0,0)) + { + temp_lower_idx.at(0,0) = j; + break; + } + } + for(int j=0;j(0,j) > upper_pos_row.at(0,0)) + { + temp_upper_idx.at(0,0) = j; + break; + } + } + + int temp = 0; + for(int j=1;j(0,j-1);k(0,k) > lower_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } + + temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; + + count = 0; + for(int k=temp_upper_idx.at(0,j-1);k(0,k) > upper_pos_row.at(0,j)) + { + temp = count; + break; + } + count++; + } + + temp_upper_idx.at(0,j) = temp_upper_idx.at(0,j-1) + temp; + } + + for(int j=0;j(i,j) = temp_lower_idx.at(0,j) + 1; + upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; + } + + lower_pos_row.release(); + upper_pos_row.release(); + temp_lower_idx.release(); + temp_upper_idx.release(); + } + for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); } void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius) { - int h = output.rows; - int w = output.cols; - int channel = output.channels(); - - compute_boxfilter(output,hz,psketch,radius); - - Mat box_filter = Mat::zeros(h,w+1,CV_32FC3); - - for(int i = 0; i < h; i++) - { - box_filter.at(i,1*channel+0) = output.at(i,0*channel+0); - box_filter.at(i,1*channel+1) = output.at(i,0*channel+1); - box_filter.at(i,1*channel+2) = output.at(i,0*channel+2); - for(int j = 2; j < w+1; j++) - { - for(int c=0;c(i,j*channel+c) = output.at(i,(j-1)*channel+c) + box_filter.at(i,(j-1)*channel+c); - } - } - - Mat indices = Mat::zeros(h,w,CV_32FC1); - Mat final = Mat::zeros(h,w,CV_32FC3); - - for(int i=0;i(i,j) = i+1; - - Mat a = Mat::zeros(h,w,CV_32FC1); - Mat b = Mat::zeros(h,w,CV_32FC1); - - for(int c=0;c(i,j) = (c+1)*flag.at(i,j); - - for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); - b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); - - } - - int p,q,r,rem; - int p1,q1,r1,rem1; - - for(int i=0;i(i,j)/(h*(w+1)); - rem = b.at(i,j) - r*h*(w+1); - q = rem/h; - p = rem - q*h; - if(q==0) - { - p=h; - q=w; - r=r-1; - } - if(p==0) - { - p=h; - q=q-1; - } - - - r1 = a.at(i,j)/(h*(w+1)); - rem1 = a.at(i,j) - r1*h*(w+1); - q1 = rem1/h; - p1 = rem1 - q1*h; - if(p1==0) - { - p1=h; - q1=q1-1; - } - - - final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) - /(upper_idx.at(i,j) - lower_idx.at(i,j)); - } - } - } - - for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); - + int h = output.rows; + int w = output.cols; + int channel = output.channels(); + + compute_boxfilter(output,hz,psketch,radius); + + Mat box_filter = Mat::zeros(h,w+1,CV_32FC3); + + for(int i = 0; i < h; i++) + { + box_filter.at(i,1*channel+0) = output.at(i,0*channel+0); + box_filter.at(i,1*channel+1) = output.at(i,0*channel+1); + box_filter.at(i,1*channel+2) = output.at(i,0*channel+2); + for(int j = 2; j < w+1; j++) + { + for(int c=0;c(i,j*channel+c) = output.at(i,(j-1)*channel+c) + box_filter.at(i,(j-1)*channel+c); + } + } + + Mat indices = Mat::zeros(h,w,CV_32FC1); + Mat final = Mat::zeros(h,w,CV_32FC3); + + for(int i=0;i(i,j) = i+1; + + Mat a = Mat::zeros(h,w,CV_32FC1); + Mat b = Mat::zeros(h,w,CV_32FC1); + + for(int c=0;c(i,j) = (c+1)*flag.at(i,j); + + for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); + b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); + + } + + int p,q,r,rem; + int p1,q1,r1,rem1; + + for(int i=0;i(i,j)/(h*(w+1)); + rem = b.at(i,j) - r*h*(w+1); + q = rem/h; + p = rem - q*h; + if(q==0) + { + p=h; + q=w; + r=r-1; + } + if(p==0) + { + p=h; + q=q-1; + } + + + r1 = a.at(i,j)/(h*(w+1)); + rem1 = a.at(i,j) - r1*h*(w+1); + q1 = rem1/h; + p1 = rem1 - q1*h; + if(p1==0) + { + p1=h; + q1=q1-1; + } + + + final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) + /(upper_idx.at(i,j) - lower_idx.at(i,j)); + } + } + } + + for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); } void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r) { - int h = img.size().height; - int w = img.size().width; - int channel = img.channels(); + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); - //////////////////////////////////// horizontal and vertical partial derivatives ///////////////////////////////// + //////////////////////////////////// horizontal and vertical partial derivatives ///////////////////////////////// - Mat derivx = Mat::zeros(h,w-1,CV_32FC3); - Mat derivy = Mat::zeros(h-1,w,CV_32FC3); + Mat derivx = Mat::zeros(h,w-1,CV_32FC3); + Mat derivy = Mat::zeros(h-1,w,CV_32FC3); - diffx(img,derivx); - diffy(img,derivy); + diffx(img,derivx); + diffy(img,derivy); - Mat distx = Mat::zeros(h,w,CV_32FC1); - Mat disty = Mat::zeros(h,w,CV_32FC1); + Mat distx = Mat::zeros(h,w,CV_32FC1); + Mat disty = Mat::zeros(h,w,CV_32FC1); - //////////////////////// Compute the l1-norm distance of neighbor pixels //////////////////////////////////////////////// + //////////////////////// Compute the l1-norm distance of neighbor pixels //////////////////////////////////////////////// - for(int i = 0; i < h; i++) - for(int j = 0,k=1; j < w-1; j++,k++) - for(int c = 0; c < channel; c++) - { - distx.at(i,k) = - distx.at(i,k) + abs(derivx.at(i,j*channel+c)); - } + for(int i = 0; i < h; i++) + for(int j = 0,k=1; j < w-1; j++,k++) + for(int c = 0; c < channel; c++) + { + distx.at(i,k) = + distx.at(i,k) + abs(derivx.at(i,j*channel+c)); + } - for(int i = 0,k=1; i < h-1; i++,k++) - for(int j = 0; j < w; j++) - for(int c = 0; c < channel; c++) - { - disty.at(k,j) = - disty.at(k,j) + abs(derivy.at(i,j*channel+c)); - } + for(int i = 0,k=1; i < h-1; i++,k++) + for(int j = 0; j < w; j++) + for(int c = 0; c < channel; c++) + { + disty.at(k,j) = + disty.at(k,j) + abs(derivy.at(i,j*channel+c)); + } - ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. ///////////////////////////// + ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. ///////////////////////////// - horiz = Mat(h,w,CV_32FC1); - vert = Mat(h,w,CV_32FC1); + horiz = Mat(h,w,CV_32FC1); + vert = Mat(h,w,CV_32FC1); - Mat final = Mat(h,w,CV_32FC3); + Mat final = Mat(h,w,CV_32FC3); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); - vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); - } + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); + vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); + } - O = Mat(h,w,CV_32FC3); + O = Mat(h,w,CV_32FC3); - for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); + for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); - O_t = Mat(w,h,CV_32FC3); + O_t = Mat(w,h,CV_32FC3); - if(flags == 2) - { + if(flags == 2) + { - ct_H = Mat(h,w,CV_32FC1); - ct_V = Mat(h,w,CV_32FC1); + ct_H = Mat(h,w,CV_32FC1); + ct_V = Mat(h,w,CV_32FC1); - for(int i = 0; i < h; i++) - { - ct_H.at(i,0) = horiz.at(i,0); - for(int j = 1; j < w; j++) - { - ct_H.at(i,j) = horiz.at(i,j) + ct_H.at(i,j-1); - } - } + for(int i = 0; i < h; i++) + { + ct_H.at(i,0) = horiz.at(i,0); + for(int j = 1; j < w; j++) + { + ct_H.at(i,j) = horiz.at(i,j) + ct_H.at(i,j-1); + } + } - for(int j = 0; j < w; j++) - { - ct_V.at(0,j) = vert.at(0,j); - for(int i = 1; i < h; i++) - { - ct_V.at(i,j) = vert.at(i,j) + ct_V.at(i-1,j); - } - } - } + for(int j = 0; j < w; j++) + { + ct_V.at(0,j) = vert.at(0,j); + for(int i = 1; i < h; i++) + { + ct_V.at(i,j) = vert.at(i,j) + ct_V.at(i-1,j); + } + } + } } + void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1) { - int no_of_iter = 3; - int h = img.size().height; - int w = img.size().width; - float sigma_h = sigma_s; + int no_of_iter = 3; + int h = img.size().height; + int w = img.size().width; + float sigma_h = sigma_s; + + init(img,flags,sigma_s,sigma_r); + + if(flags == 1) + { + Mat vert_t = vert.t(); + + for(int i=0;i(k,j) = (shade_factor * (penx.at(k,j) + peny_t.at(k,j))); - Mat vert_t = ct_V.t(); - Mat temp = Mat(h,w,CV_32FC1); - Mat temp1 = Mat(w,h,CV_32FC1); + if(i==0) + { + sketch = pen_res.clone(); - float radius; + for(int k = 0; k < h; k++) + for(int j = 0; j < w; j++) + { + Y_channel.at(k,j) = color_sketch.at(k,j*channel+0); + U_channel.at(k,j) = color_sketch.at(k,j*channel+1); + V_channel.at(k,j) = color_sketch.at(k,j*channel+2); + } - for(int i=0;i(k,j) = pen_res.at(k,j); - compute_NCfilter(O, ct_H, temp,radius); + // cvMerge(Y_channel,U_channel,V_channel,0,color_sketch); + for(int k = 0; k < h; k++) + for(int j = 0; j < w; j++) + { + color_sketch.at(k,j*channel+0) = Y_channel.at(k,j); + color_sketch.at(k,j*channel+1) = U_channel.at(k,j); + color_sketch.at(k,j*channel+2) = V_channel.at(k,j); + } - O_t = O.t(); + cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR); - compute_NCfilter(O_t, vert_t, temp1, radius); + } - O = O_t.t(); - } - } + } - res = O.clone(); } diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index 92beb02fe8..c67794ed7a 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -39,7 +39,6 @@ // //M*/ - #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -55,11 +54,11 @@ using namespace cv; void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags) { - Mat src = _src.getMat(); - Mat dest = _dst.getMat(); - Mat mask = _mask.getMat(); - _blend.create(dest.size(), CV_8UC3); - Mat blend = _blend.getMat(); + Mat src = _src.getMat(); + Mat dest = _dst.getMat(); + Mat mask = _mask.getMat(); + _blend.create(dest.size(), CV_8UC3); + Mat blend = _blend.getMat(); int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN; int h = mask.size().height; @@ -134,14 +133,14 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b) { - Mat src = _src.getMat(); - Mat mask = _mask.getMat(); - _dst.create(src.size(), src.type()); - Mat blend = _dst.getMat(); - - float red = r; - float green = g; - float blue = b; + Mat src = _src.getMat(); + Mat mask = _mask.getMat(); + _dst.create(src.size(), src.type()); + Mat blend = _dst.getMat(); + + float red = r; + float green = g; + float blue = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); @@ -149,7 +148,7 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float cvtColor(mask, gray, COLOR_BGR2GRAY ); else gray = mask; - + Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); int channel = 3; @@ -174,12 +173,12 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b) { - Mat src = _src.getMat(); - Mat mask = _mask.getMat(); - _dst.create(src.size(), src.type()); - Mat blend = _dst.getMat(); - float alpha = a; - float beta = b; + Mat src = _src.getMat(); + Mat mask = _mask.getMat(); + _dst.create(src.size(), src.type()); + Mat blend = _dst.getMat(); + float alpha = a; + float beta = b; Mat gray = Mat::zeros(mask.size(),CV_8UC1); @@ -203,19 +202,20 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, } } - + Cloning obj; obj.illum_change(src,cs_mask,gray,blend,alpha,beta); } -void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst) +void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, + double low_threshold, double high_threshold, int kernel_size) { - Mat src = _src.getMat(); - Mat mask = _mask.getMat(); - _dst.create(src.size(), src.type()); - Mat blend = _dst.getMat(); + Mat src = _src.getMat(); + Mat mask = _mask.getMat(); + _dst.create(src.size(), src.type()); + Mat blend = _dst.getMat(); Mat gray = Mat::zeros(mask.size(),CV_8UC1); @@ -239,8 +239,8 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst) } } - + Cloning obj; - obj.texture_flatten(src,cs_mask,gray,blend); + obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend); } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index a59cb5d16b..f039d2974d 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -39,7 +39,6 @@ // //M*/ - #include "precomp.hpp" #include "opencv2/photo.hpp" #include "opencv2/imgproc.hpp" @@ -74,9 +73,9 @@ class Cloning void transpose(double *mat, double *mat_t,int h,int w); void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); - void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul, float green_mul, float blue_mul); void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final); + void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final); }; void Cloning::getGradientx( const Mat &img, Mat &gx) @@ -94,6 +93,7 @@ void Cloning::getGradientx( const Mat &img, Mat &gx) (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); } } + void Cloning::getGradienty( const Mat &img, Mat &gy) { int w = img.size().width; @@ -110,6 +110,7 @@ void Cloning::getGradienty( const Mat &img, Mat &gy) } } + void Cloning::lapx( const Mat &img, Mat &gxx) { int w = img.size().width; @@ -125,6 +126,7 @@ void Cloning::lapx( const Mat &img, Mat &gxx) (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); } } + void Cloning::lapy( const Mat &img, Mat &gyy) { int w = img.size().width; @@ -242,6 +244,7 @@ void Cloning::transpose(double *mat, double *mat_t,int h,int w) tmp.release(); } + void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { @@ -275,7 +278,6 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); } - Mat diff = Mat(h,w,CV_32FC1); for(int i =0;i(i,j*channel+0) = blue; - factor.at(i,j*channel+1) = green; - factor.at(i,j*channel+2) = red; + factor.at(i,j*channel+0) = blue_mul; + factor.at(i,j*channel+1) = green_mul; + factor.at(i,j*channel+2) = red_mul; } - - for(int i=0;i < h; i++) for(int j=0; j < w; j++) for(int c=0;cget_data_path()) + "cloning/Feature_Exchange/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Monochrome_Transfer/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "destination1.png"; string original_path3 = folder + "mask.png"; @@ -174,7 +174,7 @@ TEST(Photo_SeamlessClone_textureFlattening, regression) ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2; Mat result; - textureFlattening(source, mask, result); + textureFlattening(source, mask, result, 30, 45, 3); imwrite(folder + "cloned.png", result); diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp new file mode 100644 index 0000000000..0a4b2c56ef --- /dev/null +++ b/modules/photo/test/test_npr.cpp @@ -0,0 +1,146 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + + +#include "test_precomp.hpp" +#include "opencv2/photo.hpp" +#include + +using namespace cv; +using namespace std; + + +TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + edgePreservingFilter(source,result,1); + + imwrite(folder + "smoothened_RF.png", result); + +} + +TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + edgePreservingFilter(source,result,2); + + imwrite(folder + "smoothened_NCF.png", result); + +} + +TEST(Photo_NPR_DetailEnhance, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Detail_Enhance/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + detailEnhance(source,result); + + imwrite(folder + "detail_enhanced.png", result); + +} + +TEST(Photo_NPR_PencilSketch, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Pencil_Sketch/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result,result1; + pencilSketch(source,result,result1,10,.1,.03); + + imwrite(folder + "pencil_sketch.png", result); + imwrite(folder + "color_pencil_sketch.png", result1); + +} + +TEST(Photo_NPR_Stylization, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Stylization/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + stylization(source,result); + + imwrite(folder + "stylized.png", result); + +} + +TEST(Photo_NPR_EdgeEnhance, regression) +{ + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Edge_Enhance/"; + string original_path = folder + "test1.png"; + + Mat source = imread(original_path, IMREAD_COLOR); + + ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; + + Mat result; + edgeEnhance(source,result); + + imwrite(folder + "edge_enhanced.png", result); + +} diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp index 9a41ce229b..84458fd4fe 100644 --- a/samples/cpp/cloning.cpp +++ b/samples/cpp/cloning.cpp @@ -56,18 +56,19 @@ char src[50]; char dest[50]; int var = 0; -int flag = 0; -int flag1 = 0; +int flag = 0, flag1 = 0, flag4 = 0; -int minx,miny,maxx,maxy,lenx,leny; -int minxd,minyd,maxxd,maxyd,lenxd,lenyd; +int minx, miny, maxx, maxy, lenx, leny; +int minxd, minyd, maxxd, maxyd, lenxd, lenyd; -int channel,num; +int channel, num, kernel_size; float alpha,beta; float red, green, blue; +double low_t, high_t; + void source(int event, int x, int y, int, void*) { @@ -159,7 +160,7 @@ void source(int event, int x, int y, int, void*) } else if(num == 6) { - textureFlattening(img0,res1,blend); + textureFlattening(img0,res1,blend,low_t,high_t,kernel_size); imshow("Texture Flattened", blend); waitKey(0); } @@ -176,11 +177,12 @@ void source(int event, int x, int y, int, void*) flag1 = 0; minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; imshow("Source", img0); + if(num == 1 || num == 2 || num == 3) + imshow("Destination",img2); drag = 0; } } - void destination(int event, int x, int y, int, void*) { @@ -190,6 +192,7 @@ void destination(int event, int x, int y, int, void*) im1 = img2.clone(); if (event == EVENT_LBUTTONDOWN) { + flag4 = 1; if(flag1 == 1) { point = Point(x, y); @@ -386,14 +389,12 @@ int main(int argc, char **argv) res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); - //////////// source image /////////////////// namedWindow("Source", 1); setMouseCallback("Source", source, NULL); imshow("Source", img0); - } else if(num == 5) { @@ -416,12 +417,20 @@ int main(int argc, char **argv) setMouseCallback("Source", source, NULL); imshow("Source", img0); - } else if(num == 6) { checkfile(s); + cout << "low_threshold: "; + cin >> low_t; + + cout << "high_threshold: "; + cin >> high_t; + + cout << "kernel_size: "; + cin >> kernel_size; + img0 = imread(src); res1 = Mat::zeros(img0.size(),CV_8UC1); @@ -434,13 +443,16 @@ int main(int argc, char **argv) imshow("Source", img0); } + int flag3 = 0; + while(true) { char key = waitKey(0); - if(key == 'd') + if(key == 'd' && flag3 == 0) { flag1 = 1; + flag3 = 1; img1 = img0.clone(); for(int i = var; i < numpts ; i++) pts[i] = point; @@ -490,13 +502,15 @@ int main(int argc, char **argv) } var = 0; flag1 = 0; + flag3 = 0; + flag4 = 0; minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; imshow("Source", img0); if(num == 1 || num == 2 || num == 3) imshow("Destination",img2); drag = 0; } - else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1) + else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1 && flag4 == 1) { seamlessClone(img0,img2,res1,point,blend,num); imshow("Cloned Image", blend); @@ -516,14 +530,12 @@ int main(int argc, char **argv) } else if (num == 6 && key == 'c' && flag1 == 1) { - textureFlattening(img0,res1,blend); + textureFlattening(img0,res1,blend,low_t,high_t,kernel_size); imshow("Texture Flattened", blend); imwrite("cloned.png",blend); } else if(key == 'q') exit(0); - } - waitKey(0); } diff --git a/samples/cpp/cloning_example.cpp b/samples/cpp/cloning_example.cpp new file mode 100644 index 0000000000..6c31d2f44e --- /dev/null +++ b/samples/cpp/cloning_example.cpp @@ -0,0 +1,243 @@ +/* +* cloning.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV seamless cloning +* module without GUI. +* +* 1- Normal Cloning +* 2- Mixed Cloning +* 3- Monochrome Transfer +* 4- Color Change +* 5- Illumination change +* 6- Texture Flattening + +* The program takes as input a source and a destination image (for 1-3 methods) +* and ouputs the cloned image. +*/ + +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +int main(int argc, char **argv) +{ + cout << endl; + cout << "Cloning Module" << endl; + cout << "---------------" << endl; + cout << "Options: " << endl; + cout << endl; + cout << "1) Normal Cloning " << endl; + cout << "2) Mixed Cloning " << endl; + cout << "3) Monochrome Transfer " << endl; + cout << "4) Local Color Change " << endl; + cout << "5) Local Illumination Change " << endl; + cout << "6) Texture Flattening " << endl; + cout << endl; + cout << "Press number 1-6 to choose from above techniques: "; + int num; + cin >> num; + cout << endl; + + if(num == 1) + { + string folder = "cloning/Normal_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = 400; + p.y = 100; + + seamlessClone(source, destination, mask, p, result, 1); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 2) + { + string folder = "cloning/Mixed_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 2); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 3) + { + string folder = "cloning/Monochrome_Transfer/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 4) + { + string folder = "cloning/Color_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + colorChange(source, mask, result, 1.5, .5, .5); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 5) + { + string folder = "cloning/Illumination_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + illuminationChange(source, mask, result, .2, .4); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 6) + { + string folder = "cloning/Texture_Flattening/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + textureFlattening(source, mask, result, 30, 45, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + waitKey(0); +} diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp new file mode 100644 index 0000000000..871fd32405 --- /dev/null +++ b/samples/cpp/npr_demo.cpp @@ -0,0 +1,107 @@ +/* +* npr_demo.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV Non-Photorealistic Rendering Module. +* 1) Edge Preserve Smoothing +* -> Using Normalized convolution Filter +* -> Using Recursive Filter +* 2) Detail Enhancement +* 3) Pencil sketch/Color Pencil Drawing +* 4) Stylization +* 5) Edge Enhancement +* +*/ + +#include +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +int main(int argc, char* argv[]) +{ + int num,type; + + int flag = 0; + + Mat I = imread(argv[1]); + + + if(argc < 2) + { + cout << "usage: " << argv[0] << " " << endl; + exit(0); + } + + if(!I.data) + { + cout << "Image not found" << endl; + exit(0); + } + + cout << endl; + cout << " Edge Preserve Filter" << endl; + cout << "----------------------" << endl; + + cout << "Options: " << endl; + cout << endl; + + cout << "1) Edge Preserve Smoothing" << endl; + cout << " -> Using Normalized convolution Filter" << endl; + cout << " -> Using Recursive Filter" << endl; + cout << "2) Detail Enhancement" << endl; + cout << "3) Pencil sketch/Color Pencil Drawing" << endl; + cout << "4) Stylization" << endl; + cout << "5) Edge Enhancement" << endl; + cout << endl; + + cout << "Press number 1-5 to choose from above techniques: "; + + cin >> num; + + Mat img; + + if(num == 1) + { + cout << endl; + cout << "Press 1 for Normalized Convolution Filter and 2 for Recursive Filter: "; + + cin >> type; + + edgePreservingFilter(I,img,type); + imshow("Edge Preserve Smoothing",img); + + } + else if(num == 2) + { + detailEnhance(I,img); + imshow("Detail Enhanced",img); + } + else if(num == 3) + { + Mat img1; + pencilSketch(I,img1, img, 10 ,.1,.03); + imshow("Pencil Sketch",img1); + imshow("Color Pencil Sketch",img); + } + else if(num == 4) + { + stylization(I,img); + imshow("Stylization",img); + } + else if(num == 5) + { + edgeEnhance(I,img); + imshow("Edge Enhance",img); + } + + waitKey(0); +} From 50c19423f9c4af5d3c81f75f4a3dd0a4b4abc3f3 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 13 Sep 2013 18:25:23 +0530 Subject: [PATCH 10/27] cloning demo added --- samples/cpp/cloning_demo.cpp | 243 +++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 samples/cpp/cloning_demo.cpp diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp new file mode 100644 index 0000000000..7952174648 --- /dev/null +++ b/samples/cpp/cloning_demo.cpp @@ -0,0 +1,243 @@ +/* +* cloning_demo.cpp +* +* Author: +* Siddharth Kherada +* +* This tutorial demonstrates how to use OpenCV seamless cloning +* module without GUI. +* +* 1- Normal Cloning +* 2- Mixed Cloning +* 3- Monochrome Transfer +* 4- Color Change +* 5- Illumination change +* 6- Texture Flattening + +* The program takes as input a source and a destination image (for 1-3 methods) +* and ouputs the cloned image. +*/ + +#include "opencv2/photo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/core.hpp" +#include +#include + +using namespace std; +using namespace cv; + +int main(int argc, char **argv) +{ + cout << endl; + cout << "Cloning Module" << endl; + cout << "---------------" << endl; + cout << "Options: " << endl; + cout << endl; + cout << "1) Normal Cloning " << endl; + cout << "2) Mixed Cloning " << endl; + cout << "3) Monochrome Transfer " << endl; + cout << "4) Local Color Change " << endl; + cout << "5) Local Illumination Change " << endl; + cout << "6) Texture Flattening " << endl; + cout << endl; + cout << "Press number 1-6 to choose from above techniques: "; + int num; + cin >> num; + cout << endl; + + if(num == 1) + { + string folder = "cloning/Normal_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = 400; + p.y = 100; + + seamlessClone(source, destination, mask, p, result, 1); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 2) + { + string folder = "cloning/Mixed_Cloning/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 2); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 3) + { + string folder = "cloning/Monochrome_Transfer/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "destination1.png"; + string original_path3 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat destination = imread(original_path2, IMREAD_COLOR); + Mat mask = imread(original_path3, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(destination.empty()) + { + cout << "Could not load destination image " << original_path2 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path3 << endl; + exit(0); + } + + Mat result; + Point p; + p.x = destination.size().width/2; + p.y = destination.size().height/2; + + seamlessClone(source, destination, mask, p, result, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 4) + { + string folder = "cloning/Color_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + colorChange(source, mask, result, 1.5, .5, .5); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 5) + { + string folder = "cloning/Illumination_Change/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + illuminationChange(source, mask, result, .2, .4); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + else if(num == 6) + { + string folder = "cloning/Texture_Flattening/"; + string original_path1 = folder + "source1.png"; + string original_path2 = folder + "mask.png"; + + Mat source = imread(original_path1, IMREAD_COLOR); + Mat mask = imread(original_path2, IMREAD_COLOR); + + if(source.empty()) + { + cout << "Could not load source image " << original_path1 << endl; + exit(0); + } + if(mask.empty()) + { + cout << "Could not load mask image " << original_path2 << endl; + exit(0); + } + + Mat result; + + textureFlattening(source, mask, result, 30, 45, 3); + + imshow("Output",result); + imwrite(folder + "cloned.png", result); + } + waitKey(0); +} From 7ab43585aa127225810bb497c639f529ed1d3cad Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 13 Sep 2013 18:27:02 +0530 Subject: [PATCH 11/27] remove cloning_example.cpp --- samples/cpp/cloning_example.cpp | 243 -------------------------------- 1 file changed, 243 deletions(-) delete mode 100644 samples/cpp/cloning_example.cpp diff --git a/samples/cpp/cloning_example.cpp b/samples/cpp/cloning_example.cpp deleted file mode 100644 index 6c31d2f44e..0000000000 --- a/samples/cpp/cloning_example.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* -* cloning.cpp -* -* Author: -* Siddharth Kherada -* -* This tutorial demonstrates how to use OpenCV seamless cloning -* module without GUI. -* -* 1- Normal Cloning -* 2- Mixed Cloning -* 3- Monochrome Transfer -* 4- Color Change -* 5- Illumination change -* 6- Texture Flattening - -* The program takes as input a source and a destination image (for 1-3 methods) -* and ouputs the cloned image. -*/ - -#include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/core.hpp" -#include -#include - -using namespace std; -using namespace cv; - -int main(int argc, char **argv) -{ - cout << endl; - cout << "Cloning Module" << endl; - cout << "---------------" << endl; - cout << "Options: " << endl; - cout << endl; - cout << "1) Normal Cloning " << endl; - cout << "2) Mixed Cloning " << endl; - cout << "3) Monochrome Transfer " << endl; - cout << "4) Local Color Change " << endl; - cout << "5) Local Illumination Change " << endl; - cout << "6) Texture Flattening " << endl; - cout << endl; - cout << "Press number 1-6 to choose from above techniques: "; - int num; - cin >> num; - cout << endl; - - if(num == 1) - { - string folder = "cloning/Normal_Cloning/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "destination1.png"; - string original_path3 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat destination = imread(original_path2, IMREAD_COLOR); - Mat mask = imread(original_path3, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(destination.empty()) - { - cout << "Could not load destination image " << original_path2 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path3 << endl; - exit(0); - } - - Mat result; - Point p; - p.x = 400; - p.y = 100; - - seamlessClone(source, destination, mask, p, result, 1); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 2) - { - string folder = "cloning/Mixed_Cloning/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "destination1.png"; - string original_path3 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat destination = imread(original_path2, IMREAD_COLOR); - Mat mask = imread(original_path3, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(destination.empty()) - { - cout << "Could not load destination image " << original_path2 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path3 << endl; - exit(0); - } - - Mat result; - Point p; - p.x = destination.size().width/2; - p.y = destination.size().height/2; - - seamlessClone(source, destination, mask, p, result, 2); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 3) - { - string folder = "cloning/Monochrome_Transfer/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "destination1.png"; - string original_path3 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat destination = imread(original_path2, IMREAD_COLOR); - Mat mask = imread(original_path3, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(destination.empty()) - { - cout << "Could not load destination image " << original_path2 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path3 << endl; - exit(0); - } - - Mat result; - Point p; - p.x = destination.size().width/2; - p.y = destination.size().height/2; - - seamlessClone(source, destination, mask, p, result, 3); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 4) - { - string folder = "cloning/Color_Change/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat mask = imread(original_path2, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path2 << endl; - exit(0); - } - - Mat result; - - colorChange(source, mask, result, 1.5, .5, .5); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 5) - { - string folder = "cloning/Illumination_Change/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat mask = imread(original_path2, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path2 << endl; - exit(0); - } - - Mat result; - - illuminationChange(source, mask, result, .2, .4); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - else if(num == 6) - { - string folder = "cloning/Texture_Flattening/"; - string original_path1 = folder + "source1.png"; - string original_path2 = folder + "mask.png"; - - Mat source = imread(original_path1, IMREAD_COLOR); - Mat mask = imread(original_path2, IMREAD_COLOR); - - if(source.empty()) - { - cout << "Could not load source image " << original_path1 << endl; - exit(0); - } - if(mask.empty()) - { - cout << "Could not load mask image " << original_path2 << endl; - exit(0); - } - - Mat result; - - textureFlattening(source, mask, result, 30, 45, 3); - - imshow("Output",result); - imwrite(folder + "cloned.png", result); - } - waitKey(0); -} From f8b00e52698d2caefbb6c8dc9417c720d9b1e794 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 13 Sep 2013 18:28:03 +0530 Subject: [PATCH 12/27] renamed --- samples/cpp/{cloning.cpp => cloning_gui.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename samples/cpp/{cloning.cpp => cloning_gui.cpp} (100%) diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning_gui.cpp similarity index 100% rename from samples/cpp/cloning.cpp rename to samples/cpp/cloning_gui.cpp From 01e1ccfa88d4df8667270a5f400ecf655aa08bec Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 16:47:44 +0530 Subject: [PATCH 13/27] cloning_demo error removed --- samples/cpp/cloning_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 7952174648..1992b65e98 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -28,7 +28,7 @@ using namespace std; using namespace cv; -int main(int argc, char **argv) +int main() { cout << endl; cout << "Cloning Module" << endl; From 75b76554bf9478b27e88a8ec5ef1ff239ff0bfba Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 17:06:26 +0530 Subject: [PATCH 14/27] errors in samples/cpp removed --- samples/cpp/cloning_gui.cpp | 6 +++++- samples/cpp/create_mask.cpp | 9 +++++++++ samples/cpp/npr_demo.cpp | 11 ++++------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 84458fd4fe..1d742fdd51 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -69,6 +69,10 @@ float red, green, blue; double low_t, high_t; +void source(int, int, int, int, void*); +void destination(int, int, int, int, void*); +void checkfile(char*); + void source(int event, int x, int y, int, void*) { @@ -304,7 +308,7 @@ void checkfile(char *file) } } -int main(int argc, char **argv) +int main() { cout << endl; cout << "Cloning Module" << endl; diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp index 03055e99e0..59905f1403 100644 --- a/samples/cpp/create_mask.cpp +++ b/samples/cpp/create_mask.cpp @@ -36,6 +36,8 @@ int minx,miny,maxx,maxy,lenx,leny; int channel; +void mouseHandler(int, int, int, int, void*); + void mouseHandler(int event, int x, int y, int, void*) { @@ -123,6 +125,13 @@ void mouseHandler(int event, int x, int y, int, void*) int main(int argc, char **argv) { + + if(argc != 2) + { + cout << "usage: " << argv[0] << " " << endl; + exit(1); + } + Mat src = imread(argv[1]); minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp index 871fd32405..e5e2528f13 100644 --- a/samples/cpp/npr_demo.cpp +++ b/samples/cpp/npr_demo.cpp @@ -28,19 +28,16 @@ using namespace cv; int main(int argc, char* argv[]) { - int num,type; - - int flag = 0; - - Mat I = imread(argv[1]); - - if(argc < 2) { cout << "usage: " << argv[0] << " " << endl; exit(0); } + int num,type; + + Mat I = imread(argv[1]); + if(!I.data) { cout << "Image not found" << endl; From 05c7c9325adcbfdd834891a79ec0d4e0a980273d Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 18:59:55 +0530 Subject: [PATCH 15/27] cloning_gui.cpp updated --- samples/cpp/cloning_gui.cpp | 89 +++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 1d742fdd51..4ba6b61dad 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -190,7 +190,6 @@ void source(int event, int x, int y, int, void*) void destination(int event, int x, int y, int, void*) { - Mat im1; minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; im1 = img2.clone(); @@ -250,7 +249,6 @@ void destination(int event, int x, int y, int, void*) } } - const Point* pts6[1] = {&pts2[0]}; fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0); @@ -274,40 +272,6 @@ void destination(int event, int x, int y, int, void*) im1.release(); } -void checkfile(char *file) -{ - while(1) - { - printf("Enter %s Image: ",file); - if(!strcmp(file,"Source")) - { - cin >> src; - if(access( src, F_OK ) != -1 ) - { - break; - } - else - { - printf("Image doesn't exist\n"); - } - } - else if(!strcmp(file,"Destination")) - { - cin >> dest; - - if(access( dest, F_OK ) != -1 ) - { - break; - } - else - { - printf("Image doesn't exist\n"); - } - - } - } -} - int main() { cout << endl; @@ -348,13 +312,28 @@ int main() if(num == 1 || num == 2 || num == 3) { - checkfile(s); - checkfile(d); + string src,dest; + cout << "Enter Source Image: "; + cin >> src; + + cout << "Enter Destination Image: "; + cin >> dest; img0 = imread(src); - + img2 = imread(dest); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + if(!img2.data) + { + cout << "Destination Image does not exist" << endl; + exit(0); + } + channel = img0.channels(); res = Mat::zeros(img2.size(),CV_8UC1); @@ -376,8 +355,10 @@ int main() } else if(num == 4) { - checkfile(s); - + string src; + cout << "Enter Source Image: "; + cin >> src; + cout << "Enter RGB values: " << endl; cout << "Red: "; cin >> red; @@ -390,6 +371,12 @@ int main() img0 = imread(src); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); @@ -402,7 +389,9 @@ int main() } else if(num == 5) { - checkfile(s); + string src; + cout << "Enter Source Image: "; + cin >> src; cout << "alpha: "; cin >> alpha; @@ -412,6 +401,12 @@ int main() img0 = imread(src); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); @@ -424,7 +419,9 @@ int main() } else if(num == 6) { - checkfile(s); + string src; + cout << "Enter Source Image: "; + cin >> src; cout << "low_threshold: "; cin >> low_t; @@ -437,6 +434,12 @@ int main() img0 = imread(src); + if(!img0.data) + { + cout << "Source Image does not exist" << endl; + exit(0); + } + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); From f85a615f3fbe2f8a20c5150eead1868837aa8dda Mon Sep 17 00:00:00 2001 From: siddharth Date: Sat, 14 Sep 2013 19:12:25 +0530 Subject: [PATCH 16/27] whitespaces removed and other minor changes to fix build error Update 1 update 2 Update 3 Update 4 Update 5 update 6 Update 7 Update 8 Update 9 Update 10 Update 11 Update 12 Update 13 Update 14 Update 15 Update 16 Update 17 Update 18 Update 19 Update 20 Update 21 Update 22 Removed Headers Update 23 Update 24 Update 25 Update 26 Update 27 Update 28 --- modules/photo/doc/cloning.rst | 30 +-- modules/photo/doc/decolor.rst | 1 - modules/photo/doc/npr.rst | 35 ++- modules/photo/doc/photo.rst | 5 +- modules/photo/include/opencv2/photo.hpp | 106 ++++----- modules/photo/src/contrast_preserve.cpp | 20 +- modules/photo/src/contrast_preserve.hpp | 19 +- modules/photo/src/npr.cpp | 283 ++++++++++++------------ modules/photo/src/npr.hpp | 50 ++--- modules/photo/src/seamless_cloning.cpp | 4 - modules/photo/src/seamless_cloning.hpp | 54 ++--- modules/photo/test/test_cloning.cpp | 3 +- modules/photo/test/test_decolor.cpp | 1 - modules/photo/test/test_npr.cpp | 12 +- samples/cpp/cloning_demo.cpp | 34 +-- samples/cpp/cloning_gui.cpp | 184 ++++++++------- samples/cpp/create_mask.cpp | 179 ++++++++------- 17 files changed, 495 insertions(+), 525 deletions(-) diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 11e9bce135..3a115e8390 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -9,16 +9,16 @@ Image editing tasks concern either global changes (color/intensity corrections, Here we are interested in achieving local changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless manner. The extent of the changes ranges from slight distortions to complete replacement by novel content. -.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray result, int flags) +.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray blend, int flags) :param src: Input 8-bit 3-channel image. :param dst: Input 8-bit 3-channel image. - + :param mask: Input 8-bit 1 or 3-channel image. - - :param Point: Point in dst image where object is placed. - + + :param p: Point in dst image where object is placed. + :param result: Output image with the same size and type as ``dst``. :param flags: Cloning method that could be one of the following: @@ -29,7 +29,7 @@ The extent of the changes ranges from slight distortions to complete replacement masking might be time consuming and often leaves an undesirable halo. Seamless cloning, even averaged with the original image, is not effective. Mixed seamless cloning based on a loose selection proves effective. - + * **FEATURE_EXCHANGE** Feature exchange allows the user to replace easily certain features of one object by alternative features. @@ -44,17 +44,17 @@ Given an original color image, two differently colored versions of this image ca :param src: Input 8-bit 3-channel image. :param mask: Input 8-bit 1 or 3-channel image. - + :param dst: Output image with the same size and type as ``src`` . :param red_mul: R-channel multiply factor. - + :param green_mul: G-channel multiply factor. - + :param blue_mul: B-channel multiply factor. Multiplication factor is between .5 to 2.5. - + illuminationChange ------------------ @@ -66,11 +66,11 @@ solver, modifies locally the apparent illumination of an image. :param src: Input 8-bit 3-channel image. :param mask: Input 8-bit 1 or 3-channel image. - + :param dst: Output image with the same size and type as ``src``. :param alpha: Value ranges between 0-2. - + :param beta: Value ranges between 0-2. This is useful to highlight under-exposed foreground objects or to reduce specular reflections. @@ -85,13 +85,13 @@ region, giving its contents a flat aspect. Here Canny Edge Detector is used. :param src: Input 8-bit 3-channel image. :param mask: Input 8-bit 1 or 3-channel image. - + :param dst: Output image with the same size and type as ``src``. :param low_threshold: Range from 0 to 100. - + :param high_threshold: Value > 100. - + :param kernel_size: The size of the Sobel kernel to be used. **NOTE:** diff --git a/modules/photo/doc/decolor.rst b/modules/photo/doc/decolor.rst index 061b2b18c6..cf7b9b9c4c 100644 --- a/modules/photo/doc/decolor.rst +++ b/modules/photo/doc/decolor.rst @@ -17,4 +17,3 @@ Transforms a color image to a grayscale image. It is a basic tool in digital pri :param color_boost: Output 8-bit 3-channel image. This function is to be applied on color images. - diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst index db56c6955c..e547689876 100644 --- a/modules/photo/doc/npr.rst +++ b/modules/photo/doc/npr.rst @@ -8,20 +8,20 @@ edgePreservingFilter Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications. -.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); +.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4) :param src: Input 8-bit 3-channel image. :param dst: Output 8-bit 3-channel image. - + :param flags: Edge preserving filters: - * **RECURS_FILTER** + * **RECURS_FILTER** - * **NORMCONV_FILTER** + * **NORMCONV_FILTER** :param sigma_s: Range between 0 to 200. - + :param sigma_r: Range between 0 to 1. @@ -29,33 +29,33 @@ detailEnhance ------------- This filter enhances the details of a particular image. -.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15); +.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15) :param src: Input 8-bit 3-channel image. :param dst: Output image with the same size and type as ``src``. - :param sigma_s: Range between 0 to 200. - + :param sigma_s: Range between 0 to 200. + :param sigma_r: Range between 0 to 1. - + pencilSketch ------------ Pencil-like non-photorealistic line drawing -.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); +.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02) :param src: Input 8-bit 3-channel image. :param dst1: Output 8-bit 1-channel image. - + :param dst2: Output image with the same size and type as ``src``. :param sigma_s: Range between 0 to 200. - + :param sigma_r: Range between 0 to 1. - + :param shade_factor: Range between 0 to 0.1. @@ -63,14 +63,14 @@ stylization ----------- Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features. -.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); +.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) :param src: Input 8-bit 3-channel image. :param dst: Output image with the same size and type as ``src``. :param sigma_s: Range between 0 to 200. - + :param sigma_r: Range between 0 to 1. @@ -78,13 +78,12 @@ edgeEnhance ----------- Able to suppress low-amplitude details and enhance edges. -.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); +.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) :param src: Input 8-bit 3-channel image. :param dst: Output 8-bit 1-channel image. :param sigma_s: Range between 0 to 200. - - :param sigma_r: Range between 0 to 1. + :param sigma_r: Range between 0 to 1. diff --git a/modules/photo/doc/photo.rst b/modules/photo/doc/photo.rst index c8aefda99c..676f3e9d45 100644 --- a/modules/photo/doc/photo.rst +++ b/modules/photo/doc/photo.rst @@ -9,4 +9,7 @@ photo. Computational Photography inpainting denoising - hdr_imaging \ No newline at end of file + hdr_imaging + decolor + cloning + npr diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 1eb5ccaab1..1e83608800 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -47,51 +47,51 @@ #include "opencv2/imgproc.hpp" /*! \namespace cv - Namespace where all the C++ OpenCV functionality resides + Namespace where all the C++ OpenCV functionality resides */ namespace cv { -//! the inpainting algorithm -enum -{ - INPAINT_NS = 0, // Navier-Stokes algorithm - INPAINT_TELEA = 1 // A. Telea algorithm -}; + //! the inpainting algorithm + enum + { + INPAINT_NS = 0, // Navier-Stokes algorithm + INPAINT_TELEA = 1 // A. Telea algorithm + }; -enum -{ - NORMAL_CLONE = 1, - MIXED_CLONE = 2, - MONOCHROME_TRANSFER = 3 -}; + enum + { + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + MONOCHROME_TRANSFER = 3 + }; -enum -{ - RECURS_FILTER = 1, - NORMCONV_FILTER = 2 -}; + enum + { + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 + }; -//! restores the damaged image areas using one of the available intpainting algorithms -CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, - OutputArray dst, double inpaintRadius, int flags ); + //! restores the damaged image areas using one of the available intpainting algorithms + CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, + OutputArray dst, double inpaintRadius, int flags ); -CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, - int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, + int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); -CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); + CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); enum { LDR_SIZE = 256 }; @@ -301,35 +301,35 @@ public: CV_EXPORTS_W Ptr createMergeRobertson(); -CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); + CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); -CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, - OutputArray _blend, int flags); + CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray blend, int flags); -CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, - float green_mul = 1.0, float blue_mul = 1.0); + CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, + float green_mul = 1.0, float blue_mul = 1.0); -CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, - float alpha = 0.2, float beta = 0.4); + CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2, float beta = 0.4); -CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold, double high_threshold, - int kernel_size); + CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + double low_threshold, double high_threshold, + int kernel_size); -CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, - float sigma_s = 60, float sigma_r = 0.4); + CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4); -CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, - float sigma_r = 0.15); + CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15); -CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst, OutputArray dst1, - float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); + CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, + float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); -CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); + CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); -CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); + CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); } // cv diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 14ed6ac30f..56912199ea 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -42,8 +42,6 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" -#include #include "math.h" #include #include @@ -53,21 +51,21 @@ using namespace std; using namespace cv; -double norm(double); +double norm_m(double); -double norm(double E) +double norm_m(double E) { - return (sqrt(pow(E,2))); + return sqrt(pow(E,2)); } -void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) +void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) { Mat I = _src.getMat(); _dst.create(I.size(), CV_8UC1); Mat dst = _dst.getMat(); - _boost.create(I.size(), CV_8UC3); - Mat color_boost = _boost.getMat(); + _color_boost.create(I.size(), CV_8UC3); + Mat color_boost = _color_boost.getMat(); if(!I.data ) { @@ -82,7 +80,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) int maxIter = 15; int iterCount = 0; - float tol = .0001; + double tol = .0001; double E = 0; double pre_E = std::numeric_limits::infinity(); @@ -113,7 +111,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) //////////////////////////////// main loop starting //////////////////////////////////////// - while(norm(E-pre_E) > tol) + while(norm_m(E-pre_E) > tol) { iterCount +=1; pre_E = E; @@ -223,7 +221,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) for(int i =0;i(i,j) = 255.0*Gray.at(i,j); + l.at(i,j) = dst.at(i,j); } for(int i =0;i #include @@ -124,12 +123,12 @@ void Decolor::init() vector Decolor::product(vector < vector > &comb, vector &initRGB) { vector res; - float dp; + double dp; for (unsigned int i=0;i > &poly, vector (i,j) = poly[i][j]; + P.at(i,j) = (float) poly[i][j]; - Mat P_trans = P.t(); + Mat P_trans = P.t(); Mat B = Mat(poly.size(),poly[0].size(), CV_32FC1); for(unsigned int i =0;i < poly.size();i++) { for(unsigned int j=0;j(i,j) = poly[i][j]*Cg[j]; + B.at(i,j) = (float) (poly[i][j] * Cg[j]); } A = P*P_trans; @@ -486,14 +485,14 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* pow(blue.at(i,j),b); kk=kk+1; } - double minval = INT_MAX; - double maxval = INT_MIN; + float minval = INT_MAX; + float maxval = INT_MIN; for(int i=0;i #include @@ -54,215 +51,215 @@ using namespace cv; void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC3); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); - int h = I.size().height; - int w = I.size().width; + int h = I.size().height; + int w = I.size().width; - Mat res = Mat(h,w,CV_32FC3); - dst.convertTo(res,CV_32FC3,1.0/255.0); + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); - Domain_Filter obj; + Domain_Filter obj; - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - obj.filter(img, res, sigma_s, sigma_r, flags); + obj.filter(img, res, sigma_s, sigma_r, flags); - convertScaleAbs(res, dst, 255,0); + convertScaleAbs(res, dst, 255,0); } void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC3); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); - int h = I.size().height; - int w = I.size().width; - int channel = I.channels(); - float factor = 3.0; + int h = I.size().height; + int w = I.size().width; + int channel = I.channels(); + float factor = 3.0; - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - - Mat res = Mat(h,w,CV_32FC3); - dst.convertTo(res,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - Mat result = Mat(img.size(),CV_32FC3); - Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); + Mat res = Mat(h,w,CV_32FC3); + dst.convertTo(res,CV_32FC3,1.0/255.0); - cvtColor(img,lab,COLOR_BGR2Lab); + Mat result = Mat(img.size(),CV_32FC3); + Mat lab = Mat(img.size(),CV_32FC3); + Mat l_channel = Mat(img.size(),CV_32FC1); + Mat a_channel = Mat(img.size(),CV_32FC1); + Mat b_channel = Mat(img.size(),CV_32FC1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - l_channel.at(i,j) = lab.at(i,j*channel+0); - a_channel.at(i,j) = lab.at(i,j*channel+1); - b_channel.at(i,j) = lab.at(i,j*channel+2); - } + cvtColor(img,lab,COLOR_BGR2Lab); - Mat L = Mat(img.size(),CV_32FC1); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + l_channel.at(i,j) = lab.at(i,j*channel+0); + a_channel.at(i,j) = lab.at(i,j*channel+1); + b_channel.at(i,j) = lab.at(i,j*channel+2); + } - l_channel.convertTo(L,CV_32FC1,1.0/255.0); + Mat L = Mat(img.size(),CV_32FC1); - Domain_Filter obj; + l_channel.convertTo(L,CV_32FC1,1.0/255.0); - obj.filter(L, res, sigma_s, sigma_r, 1); + Domain_Filter obj; - Mat detail = Mat(h,w,CV_32FC1); + obj.filter(L, res, sigma_s, sigma_r, 1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - detail.at(i,j) = L.at(i,j) - res.at(i,j); + Mat detail = Mat(h,w,CV_32FC1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + detail.at(i,j) = L.at(i,j) - res.at(i,j); - L.convertTo(l_channel,CV_32FC1,255); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - lab.at(i,j*channel+0) = l_channel.at(i,j); - lab.at(i,j*channel+1) = a_channel.at(i,j); - lab.at(i,j*channel+2) = b_channel.at(i,j); - } + L.convertTo(l_channel,CV_32FC1,255); - cvtColor(lab,result,COLOR_Lab2BGR); - result.convertTo(dst,CV_8UC3,255); + for(int i = 0; i < h; i++) + for(int j = 0; j < w; j++) + { + lab.at(i,j*channel+0) = l_channel.at(i,j); + lab.at(i,j*channel+1) = a_channel.at(i,j); + lab.at(i,j*channel+2) = b_channel.at(i,j); + } + + cvtColor(lab,result,COLOR_Lab2BGR); + result.convertTo(dst,CV_8UC3,255); } -void cv::pencilSketch(InputArray _src, OutputArray _dst, OutputArray _dst1, float sigma_s, float sigma_r, float shade_factor) +void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, float sigma_s, float sigma_r, float shade_factor) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC1); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst1.create(I.size(), CV_8UC1); + Mat dst1 = _dst1.getMat(); + + _dst2.create(I.size(), CV_8UC3); + Mat dst2 = _dst2.getMat(); - _dst1.create(I.size(), CV_8UC3); - Mat dst1 = _dst1.getMat(); - - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - Domain_Filter obj; + Domain_Filter obj; - Mat sketch = Mat(I.size(),CV_32FC1); - Mat color_sketch = Mat(I.size(),CV_32FC3); + Mat sketch = Mat(I.size(),CV_32FC1); + Mat color_sketch = Mat(I.size(),CV_32FC3); - obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor); + obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor); - sketch.convertTo(dst,CV_8UC1,255); - color_sketch.convertTo(dst1,CV_8UC3,255); + sketch.convertTo(dst1,CV_8UC1,255); + color_sketch.convertTo(dst2,CV_8UC3,255); } void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC3); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC3); + Mat dst = _dst.getMat(); - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - int h = img.size().height; - int w = img.size().width; - int channel = img.channels(); + int h = img.size().height; + int w = img.size().width; + int channel = img.channels(); - Mat res = Mat(h,w,CV_32FC3); + Mat res = Mat(h,w,CV_32FC3); - Domain_Filter obj; - obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + Domain_Filter obj; + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - vector planes; - split(res, planes); + vector planes; + split(res, planes); - Mat magXR = Mat(h, w, CV_32FC1); - Mat magYR = Mat(h, w, CV_32FC1); + Mat magXR = Mat(h, w, CV_32FC1); + Mat magYR = Mat(h, w, CV_32FC1); - Mat magXG = Mat(h, w, CV_32FC1); - Mat magYG = Mat(h, w, CV_32FC1); + Mat magXG = Mat(h, w, CV_32FC1); + Mat magYG = Mat(h, w, CV_32FC1); - Mat magXB = Mat(h, w, CV_32FC1); - Mat magYB = Mat(h, w, CV_32FC1); + Mat magXB = Mat(h, w, CV_32FC1); + Mat magYB = Mat(h, w, CV_32FC1); - Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); - Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); - Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); - Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); - Mat magx = Mat(h,w,CV_32FC1); - Mat magy = Mat(h,w,CV_32FC1); + Mat magx = Mat(h,w,CV_32FC1); + Mat magy = Mat(h,w,CV_32FC1); - Mat mag1 = Mat(h,w,CV_32FC1); - Mat mag2 = Mat(h,w,CV_32FC1); - Mat mag3 = Mat(h,w,CV_32FC1); + Mat mag1 = Mat(h,w,CV_32FC1); + Mat mag2 = Mat(h,w,CV_32FC1); + Mat mag3 = Mat(h,w,CV_32FC1); - magnitude(magXR,magYR,mag1); - magnitude(magXG,magYG,mag2); - magnitude(magXB,magYB,mag3); + magnitude(magXR,magYR,mag1); + magnitude(magXG,magYG,mag2); + magnitude(magXB,magYB,mag3); - Mat magnitude = Mat(h,w,CV_32FC1); + Mat magnitude = Mat(h,w,CV_32FC1); - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); - } + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); + } - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = 1.0 - magnitude.at(i,j); - } + for(int i =0;i < h;i++) + for(int j=0;j(i,j) = 1.0f - magnitude.at(i,j); + } - Mat stylized = Mat(h,w,CV_32FC3); + Mat stylized = Mat(h,w,CV_32FC3); - for(int i =0;i < h;i++) - for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); - } + for(int i =0;i < h;i++) + for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); + } - stylized.convertTo(dst,CV_8UC3,255); + stylized.convertTo(dst,CV_8UC3,255); } void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) { - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC1); - Mat dst = _dst.getMat(); + Mat I = _src.getMat(); + _dst.create(I.size(), CV_8UC1); + Mat dst = _dst.getMat(); - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); + Mat img = Mat(I.size(),CV_32FC3); + I.convertTo(img,CV_32FC3,1.0/255.0); - Mat orig = img.clone(); + Mat orig = img.clone(); - int h = img.size().height; - int w = img.size().width; + int h = img.size().height; + int w = img.size().width; - Mat res = Mat(h,w,CV_32FC3); - Mat magnitude = Mat(h,w,CV_32FC1); + Mat res = Mat(h,w,CV_32FC3); + Mat magnitude = Mat(h,w,CV_32FC1); - Mat mag8 = Mat(h,w,CV_32FC1); + Mat mag8 = Mat(h,w,CV_32FC1); - Domain_Filter obj; + Domain_Filter obj; - obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); + obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - obj.find_magnitude(res,magnitude); + obj.find_magnitude(res,magnitude); - magnitude.convertTo(dst,CV_8UC1,255); + magnitude.convertTo(dst,CV_8UC1,255); } diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 66638ccbd8..3f5519d1bb 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -41,12 +41,12 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" #include #include #include #include "math.h" + using namespace std; using namespace cv; @@ -79,7 +79,7 @@ void Domain_Filter::diffx(const Mat &img, Mat &temp) { for(int c =0; c < channel; c++) { - temp.at(i,j*channel+c) = + temp.at(i,j*channel+c) = img.at(i,(j+1)*channel+c) - img.at(i,j*channel+c); } } @@ -94,7 +94,7 @@ void Domain_Filter::diffy(const Mat &img, Mat &temp) { for(int c =0; c < channel; c++) { - temp.at(i,j*channel+c) = + temp.at(i,j*channel+c) = img.at((i+1),j*channel+c) - img.at(i,j*channel+c); } } @@ -179,7 +179,7 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag) for(int i =0;i < h;i++) for(int j=0;j(i,j) = 1.0 - mag.at(i,j); + mag.at(i,j) = 1.0f - mag.at(i,j); } } @@ -193,7 +193,7 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) int w = output.cols; int channel = output.channels(); - a = exp(-sqrt(2) / sigma_h); + a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); Mat temp = Mat(h,w,CV_32FC3); @@ -202,21 +202,19 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) for(int c=0;c(i,j*channel+c) = output.at(i,j*channel+c); - Mat V = Mat(h,w,CV_32FC1); for(int i=0;i(i,j) = pow(a,hz.at(i,j)); - for(int i=0; i(i,j*channel+c) = temp.at(i,j*channel+c) + + temp.at(i,j*channel+c) = temp.at(i,j*channel+c) + (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); } } @@ -267,7 +265,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float { for(int j=0;j(0,j) = hz.at(i,j); - domain_row.at(0,w) = myinf; + domain_row.at(0,w) = (float) myinf; Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1); Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1); @@ -285,7 +283,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float { if(domain_row.at(0,j) > lower_pos_row.at(0,0)) { - temp_lower_idx.at(0,0) = j; + temp_lower_idx.at(0,0) = (float) j; break; } } @@ -293,7 +291,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float { if(domain_row.at(0,j) > upper_pos_row.at(0,0)) { - temp_upper_idx.at(0,0) = j; + temp_upper_idx.at(0,0) = (float) j; break; } } @@ -302,7 +300,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float for(int j=1;j(0,j-1);k(0,j-1);k(0,k) > lower_pos_row.at(0,j)) { @@ -315,7 +313,7 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float temp_lower_idx.at(0,j) = temp_lower_idx.at(0,j-1) + temp; count = 0; - for(int k=temp_upper_idx.at(0,j-1);k(0,j-1);k(i,j) = i+1; + indices.at(i,j) = (float) i+1; Mat a = Mat::zeros(h,w,CV_32FC1); Mat b = Mat::zeros(h,w,CV_32FC1); @@ -402,8 +400,8 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r for(int j=0;j(i,j)/(h*(w+1)); - rem = b.at(i,j) - r*h*(w+1); + r = (int) b.at(i,j)/(h*(w+1)); + rem = (int) b.at(i,j) - r*h*(w+1); q = rem/h; p = rem - q*h; if(q==0) @@ -419,8 +417,8 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r } - r1 = a.at(i,j)/(h*(w+1)); - rem1 = a.at(i,j) - r1*h*(w+1); + r1 = (int) a.at(i,j)/(h*(w+1)); + rem1 = (int) a.at(i,j) - r1*h*(w+1); q1 = rem1/h; p1 = rem1 - q1*h; if(p1==0) @@ -465,7 +463,7 @@ void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r for(int j = 0,k=1; j < w-1; j++,k++) for(int c = 0; c < channel; c++) { - distx.at(i,k) = + distx.at(i,k) = distx.at(i,k) + abs(derivx.at(i,j*channel+c)); } @@ -473,7 +471,7 @@ void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r for(int j = 0; j < w; j++) for(int c = 0; c < channel; c++) { - disty.at(k,j) = + disty.at(k,j) = disty.at(k,j) + abs(derivy.at(i,j*channel+c)); } @@ -539,11 +537,11 @@ void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float s if(flags == 1) { - Mat vert_t = vert.t(); + Mat vert_t = vert.t(); for(int i=0;i #include @@ -243,4 +240,3 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, Cloning obj; obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend); } - diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index f039d2974d..b000e1a303 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -41,9 +41,6 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/imgproc.hpp" -#include "opencv2/highgui.hpp" -#include "opencv2/core.hpp" #include #include #include @@ -162,7 +159,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int j=0,r=1;j(r,0) = gtest[idx]; + temp.at(r,0) = (float) gtest[idx]; } temp.at(h+1,0)=0.0; @@ -170,7 +167,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int j=h-1, r=h+2;j>=0;j--,r++) { idx = j*w+i; - temp.at(r,0) = -1*gtest[idx]; + temp.at(r,0) = (float) (-1.0 * gtest[idx]); } merge(planes, 2, complex1); @@ -179,7 +176,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; - split(complex1, planes1); + split(complex1, planes1); std::complex two_i = std::sqrt(std::complex(-1)); @@ -187,7 +184,7 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int c=1,z=0;c(z,0) = planes1[1].at(c,0)/fac; + res.at(z,0) = (float) (planes1[1].at(c,0)/fac); } for(int q=0,z=0;q(i,j) = mat[idx]; + tmp.at(i,j) = (float) mat[idx]; } } Mat tmp_t = tmp.t(); @@ -264,7 +261,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int i =1;i(i,j) = 0.0; + bound.at(i,j) = 0; } double *f_bp = new double[h*w]; @@ -284,7 +281,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int j=0;j(i,j) = (lap.at(i,j) - f_bp[idx]); + diff.at(i,j) = (float) (lap.at(i,j) - f_bp[idx]); } } @@ -336,7 +333,6 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) gfinal_t[idx] = gfinal_t[idx]/denom[idx]; } - idst(gfinal_t,f3,h-2,w-2); transpose(f3,f3_t,h-2,w-2); @@ -350,7 +346,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int j = 0 ; j < w; j++) { idx = i*w + j; - img_d[idx] = (double)img.at(i,j); + img_d[idx] = (double)img.at(i,j); } } for(int i = 1 ; i < h-1;i++) @@ -358,7 +354,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) for(int j = 1 ; j < w-1; j++) { idx = i*w + j; - img_d[idx] = 0.0; + img_d[idx] = 0.0; } } for(int i = 1,id1=0 ; i < h-1;i++,id1++) @@ -367,7 +363,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { idx = i*w + j; idx1= id1*(w-2) + id2; - img_d[idx] = f3_t[idx1]; + img_d[idx] = f3_t[idx1]; } } @@ -379,9 +375,9 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) if(img_d[idx] < 0.0) result.at(i,j) = 0; else if(img_d[idx] > 255.0) - result.at(i,j) = 255.0; + result.at(i,j) = 255; else - result.at(i,j) = img_d[idx]; + result.at(i,j) = (uchar) img_d[idx]; } } @@ -410,8 +406,8 @@ void Cloning::init(Mat &I, Mat &wmask) for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); + r_channel.at(i,j) = I.at(i,j*3+0); + g_channel.at(i,j) = I.at(i,j*3+1); b_channel.at(i,j) = I.at(i,j*3+2); } @@ -453,8 +449,8 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); + rx_channel.at(i,j) = gxx.at(i,j*3+0); + gx_channel.at(i,j) = gxx.at(i,j*3+1); bx_channel.at(i,j) = gxx.at(i,j*3+2); } @@ -465,8 +461,8 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); + ry_channel.at(i,j) = gyy.at(i,j*3+0); + gy_channel.at(i,j) = gyy.at(i,j*3+1); by_channel.at(i,j) = gyy.at(i,j*3+2); } @@ -474,18 +470,10 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) resultg = Mat(I.size(),CV_8UC1); resultb = Mat(I.size(),CV_8UC1); - clock_t tic = clock(); - - poisson_solver(r_channel,rx_channel, ry_channel,resultr); poisson_solver(g_channel,gx_channel, gy_channel,resultg); poisson_solver(b_channel,bx_channel, by_channel,resultb); - clock_t toc = clock(); - - printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC); - - } void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) @@ -562,8 +550,8 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) for(int i=0;i(i,j*3+0) = gray.at(i,j); - gray8.at(i,j*3+1) = gray.at(i,j); + gray8.at(i,j*3+0) = gray.at(i,j); + gray8.at(i,j*3+1) = gray.at(i,j); gray8.at(i,j*3+2) = gray.at(i,j); } diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp index e6fbf3e6a3..761b6e0d70 100644 --- a/modules/photo/test/test_cloning.cpp +++ b/modules/photo/test/test_cloning.cpp @@ -125,7 +125,7 @@ TEST(Photo_SeamlessClone_featureExchange, regression) TEST(Photo_SeamlessClone_colorChange, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Color_Change/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/color_change/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "mask.png"; @@ -179,4 +179,3 @@ TEST(Photo_SeamlessClone_textureFlattening, regression) imwrite(folder + "cloned.png", result); } - diff --git a/modules/photo/test/test_decolor.cpp b/modules/photo/test/test_decolor.cpp index c218c6a4fa..bf21f37384 100644 --- a/modules/photo/test/test_decolor.cpp +++ b/modules/photo/test/test_decolor.cpp @@ -65,4 +65,3 @@ TEST(Photo_Decolor, regression) imwrite(folder + "color_boost.png",color_boost); } - diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp index 0a4b2c56ef..5d55d4c3b4 100644 --- a/modules/photo/test/test_npr.cpp +++ b/modules/photo/test/test_npr.cpp @@ -50,7 +50,7 @@ using namespace std; TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -66,7 +66,7 @@ TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression) TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -82,7 +82,7 @@ TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression) TEST(Photo_NPR_DetailEnhance, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Detail_Enhance/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -98,7 +98,7 @@ TEST(Photo_NPR_DetailEnhance, regression) TEST(Photo_NPR_PencilSketch, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Pencil_Sketch/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -115,7 +115,7 @@ TEST(Photo_NPR_PencilSketch, regression) TEST(Photo_NPR_Stylization, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Stylization/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); @@ -131,7 +131,7 @@ TEST(Photo_NPR_Stylization, regression) TEST(Photo_NPR_EdgeEnhance, regression) { - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Edge_Enhance/"; + string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; string original_path = folder + "test1.png"; Mat source = imread(original_path, IMREAD_COLOR); diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 1992b65e98..d9bcfb3eb6 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -46,14 +46,14 @@ int main() int num; cin >> num; cout << endl; - + if(num == 1) { string folder = "cloning/Normal_Cloning/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "destination1.png"; string original_path3 = folder + "mask.png"; - + Mat source = imread(original_path1, IMREAD_COLOR); Mat destination = imread(original_path2, IMREAD_COLOR); Mat mask = imread(original_path3, IMREAD_COLOR); @@ -63,7 +63,7 @@ int main() cout << "Could not load source image " << original_path1 << endl; exit(0); } - if(destination.empty()) + if(destination.empty()) { cout << "Could not load destination image " << original_path2 << endl; exit(0); @@ -78,24 +78,24 @@ int main() Point p; p.x = 400; p.y = 100; - + seamlessClone(source, destination, mask, p, result, 1); - + imshow("Output",result); imwrite(folder + "cloned.png", result); } else if(num == 2) - { + { string folder = "cloning/Mixed_Cloning/"; string original_path1 = folder + "source1.png"; string original_path2 = folder + "destination1.png"; string original_path3 = folder + "mask.png"; - + Mat source = imread(original_path1, IMREAD_COLOR); Mat destination = imread(original_path2, IMREAD_COLOR); Mat mask = imread(original_path3, IMREAD_COLOR); - if(source.empty()) + if(source.empty()) { cout << "Could not load source image " << original_path1 << endl; exit(0); @@ -105,7 +105,7 @@ int main() cout << "Could not load destination image " << original_path2 << endl; exit(0); } - if(mask.empty()) + if(mask.empty()) { cout << "Could not load mask image " << original_path3 << endl; exit(0); @@ -115,7 +115,7 @@ int main() Point p; p.x = destination.size().width/2; p.y = destination.size().height/2; - + seamlessClone(source, destination, mask, p, result, 2); imshow("Output",result); @@ -137,12 +137,12 @@ int main() cout << "Could not load source image " << original_path1 << endl; exit(0); } - if(destination.empty()) + if(destination.empty()) { cout << "Could not load destination image " << original_path2 << endl; exit(0); } - if(mask.empty()) + if(mask.empty()) { cout << "Could not load mask image " << original_path3 << endl; exit(0); @@ -152,7 +152,7 @@ int main() Point p; p.x = destination.size().width/2; p.y = destination.size().height/2; - + seamlessClone(source, destination, mask, p, result, 3); imshow("Output",result); @@ -179,7 +179,7 @@ int main() } Mat result; - + colorChange(source, mask, result, 1.5, .5, .5); imshow("Output",result); @@ -194,7 +194,7 @@ int main() Mat source = imread(original_path1, IMREAD_COLOR); Mat mask = imread(original_path2, IMREAD_COLOR); - if(source.empty()) + if(source.empty()) { cout << "Could not load source image " << original_path1 << endl; exit(0); @@ -206,7 +206,7 @@ int main() } Mat result; - + illuminationChange(source, mask, result, .2, .4); imshow("Output",result); @@ -233,7 +233,7 @@ int main() } Mat result; - + textureFlattening(source, mask, result, 30, 45, 3); imshow("Output",result); diff --git a/samples/cpp/cloning_gui.cpp b/samples/cpp/cloning_gui.cpp index 4ba6b61dad..2457b12154 100644 --- a/samples/cpp/cloning_gui.cpp +++ b/samples/cpp/cloning_gui.cpp @@ -52,9 +52,6 @@ Point* pts = new Point[100]; Point* pts2 = new Point[100]; Point* pts_diff = new Point[100]; -char src[50]; -char dest[50]; - int var = 0; int flag = 0, flag1 = 0, flag4 = 0; @@ -76,39 +73,38 @@ void checkfile(char*); void source(int event, int x, int y, int, void*) { - if (event == EVENT_LBUTTONDOWN && !drag) - { - if(flag1 == 0) - { - if(var==0) - img1 = img0.clone(); - point = Point(x, y); - circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); - pts[var] = point; - var++; - drag = 1; - if(var>1) - line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); - - imshow("Source", img1); - } - } - - - if (event == EVENT_LBUTTONUP && drag) - { - imshow("Source", img1); - - drag = 0; - } - if (event == EVENT_RBUTTONDOWN) - { - flag1 = 1; - img1 = img0.clone(); - for(int i = var; i < numpts ; i++) - pts[i] = point; - - if(var!=0) + if (event == EVENT_LBUTTONDOWN && !drag) + { + if(flag1 == 0) + { + if(var==0) + img1 = img0.clone(); + point = Point(x, y); + circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); + pts[var] = point; + var++; + drag = 1; + if(var>1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) { const Point* pts3[1] = {&pts[0]}; polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); @@ -169,67 +165,67 @@ void source(int event, int x, int y, int, void*) waitKey(0); } - } - if (event == EVENT_MBUTTONDOWN) - { - for(int i = 0; i < numpts ; i++) - { - pts[i].x=0; - pts[i].y=0; - } - var = 0; - flag1 = 0; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; - imshow("Source", img0); + } + if (event == EVENT_MBUTTONDOWN) + { + for(int i = 0; i < numpts ; i++) + { + pts[i].x=0; + pts[i].y=0; + } + var = 0; + flag1 = 0; + minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; + imshow("Source", img0); if(num == 1 || num == 2 || num == 3) imshow("Destination",img2); - drag = 0; - } + drag = 0; + } } void destination(int event, int x, int y, int, void*) { - Mat im1; - minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; - im1 = img2.clone(); - if (event == EVENT_LBUTTONDOWN) - { + Mat im1; + minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + im1 = img2.clone(); + if (event == EVENT_LBUTTONDOWN) + { flag4 = 1; - if(flag1 == 1) - { - point = Point(x, y); + if(flag1 == 1) + { + point = Point(x, y); for(int i=0;i im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0) { @@ -254,7 +250,7 @@ void destination(int event, int x, int y, int, void*) if(num == 1 || num == 2 || num == 3) { - seamlessClone(img0,img2,res1,point,blend,num); + seamlessClone(img0,img2,res1,point,blend,num); imshow("Cloned Image", blend); imwrite("cloned.png",blend); waitKey(0); @@ -302,25 +298,24 @@ int main() cin >> num; cout << endl; - char s[]="Source"; - char d[]="Destination"; - minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN; + int flag3 = 0; + if(num == 1 || num == 2 || num == 3) { string src,dest; cout << "Enter Source Image: "; cin >> src; - + cout << "Enter Destination Image: "; cin >> dest; img0 = imread(src); - + img2 = imread(dest); if(!img0.data) @@ -333,7 +328,7 @@ int main() cout << "Destination Image does not exist" << endl; exit(0); } - + channel = img0.channels(); res = Mat::zeros(img2.size(),CV_8UC1); @@ -358,7 +353,7 @@ int main() string src; cout << "Enter Source Image: "; cin >> src; - + cout << "Enter RGB values: " << endl; cout << "Red: "; cin >> red; @@ -428,10 +423,10 @@ int main() cout << "high_threshold: "; cin >> high_t; - + cout << "kernel_size: "; cin >> kernel_size; - + img0 = imread(src); if(!img0.data) @@ -439,7 +434,7 @@ int main() cout << "Source Image does not exist" << endl; exit(0); } - + res1 = Mat::zeros(img0.size(),CV_8UC1); final = Mat::zeros(img0.size(),CV_8UC3); @@ -449,12 +444,15 @@ int main() setMouseCallback("Source", source, NULL); imshow("Source", img0); } - - int flag3 = 0; - - while(true) + else + { + cout << "Wrong Option Choosen" << endl; + exit(0); + } + + for(;;) { - char key = waitKey(0); + char key = (char) waitKey(0); if(key == 'd' && flag3 == 0) { diff --git a/samples/cpp/create_mask.cpp b/samples/cpp/create_mask.cpp index 59905f1403..6da64d738f 100644 --- a/samples/cpp/create_mask.cpp +++ b/samples/cpp/create_mask.cpp @@ -1,4 +1,4 @@ - /* +/* * create_mask.cpp * * Author: @@ -9,8 +9,6 @@ * mask image. */ - - #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/core.hpp" @@ -41,86 +39,85 @@ void mouseHandler(int, int, int, int, void*); void mouseHandler(int event, int x, int y, int, void*) { - if (event == EVENT_LBUTTONDOWN && !drag) - { - if(flag1 == 0) - { - if(var==0) - img1 = img0.clone(); - point = Point(x, y); - circle(img1,point,2,Scalar(0, 0, 255),-1, 8, 0); - pts[var] = point; - var++; - drag = 1; - if(var>1) - line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); - - imshow("Source", img1); - } - } - - - if (event == EVENT_LBUTTONUP && drag) - { - imshow("Source", img1); - - drag = 0; - } - if (event == EVENT_RBUTTONDOWN) - { - flag1 = 1; - img1 = img0.clone(); - for(int i = var; i < numpts ; i++) - pts[i] = point; - - if(var!=0) - { - const Point* pts3[1] = {&pts[0]}; - polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); - } - - for(int i=0;i1) + line(img1,pts[var-2], point, Scalar(0, 0, 255), 2, 8, 0); + + imshow("Source", img1); + } + } + + if (event == EVENT_LBUTTONUP && drag) + { + imshow("Source", img1); + + drag = 0; + } + if (event == EVENT_RBUTTONDOWN) + { + flag1 = 1; + img1 = img0.clone(); + for(int i = var; i < numpts ; i++) + pts[i] = point; + + if(var!=0) + { + const Point* pts3[1] = {&pts[0]}; + polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0); + } + + for(int i=0;i Date: Tue, 1 Oct 2013 18:35:53 +0530 Subject: [PATCH 17/27] Changed STL in contrast_preserve file --- modules/photo/src/contrast_preserve.cpp | 6 ++-- modules/photo/src/contrast_preserve.hpp | 42 +++++++++++++++++++++---- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 56912199ea..103322a1b2 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -55,7 +55,7 @@ double norm_m(double); double norm_m(double E) { - return sqrt(pow(E,2)); + return sqroot(power(E,2)); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) @@ -136,8 +136,8 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) double ans1 = 0.0; for(unsigned int i =0;i &Cg, vector < vector > &polyGrad, vector &wei) @@ -99,7 +129,7 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } for(unsigned int i=0;i &Cg) double res =0.0; for(unsigned int i=0;i > &polyGrad, for(int i = 0;i(i,j)= - pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + power(red.at(i,j),r)*power(green.at(i,j),g)* + power(blue.at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); @@ -485,8 +515,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + (float) wei[kk]*power(red.at(i,j),r)*power(green.at(i,j),g)* + power(blue.at(i,j),b); kk=kk+1; } From 6c7272bde1a8ecc2cd00203116576bb3f2fa5152 Mon Sep 17 00:00:00 2001 From: siddharth Date: Tue, 1 Oct 2013 20:22:10 +0530 Subject: [PATCH 18/27] Update to remove Android error --- modules/photo/src/contrast_preserve.cpp | 2 +- modules/photo/src/contrast_preserve.hpp | 2 +- modules/photo/src/seamless_cloning.hpp | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 103322a1b2..9c7227405d 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -55,7 +55,7 @@ double norm_m(double); double norm_m(double E) { - return sqroot(power(E,2)); + return sqrt(power(E,2)); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index eff1530df5..587e431e08 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -235,7 +235,7 @@ void Decolor::colorGrad(Mat img, vector &Cg) double res =0.0; for(unsigned int i=0;i(i,j*channel+c) = - sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); + sqrt(power(srx32.at(i,j*channel+c),2) + power(sry32.at(i,j*channel+c),2)); } for(int i=0;i < h; i++) @@ -738,9 +750,9 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph if(srx32.at(i,j*channel+c) != 0) { srx32.at(i,j*channel+c) = - pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + power(alpha,beta)*srx32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); sry32.at(i,j*channel+c) = - pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); + power(alpha,beta)*sry32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); } } From 94eab9babe652e753bcb15bdeec65d6b6061eee8 Mon Sep 17 00:00:00 2001 From: siddharth Date: Tue, 1 Oct 2013 21:13:41 +0530 Subject: [PATCH 19/27] Revert Back --- modules/photo/src/contrast_preserve.cpp | 6 ++-- modules/photo/src/contrast_preserve.hpp | 42 ++++--------------------- modules/photo/src/seamless_cloning.hpp | 18 ++--------- 3 files changed, 12 insertions(+), 54 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 9c7227405d..56912199ea 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -55,7 +55,7 @@ double norm_m(double); double norm_m(double E) { - return sqrt(power(E,2)); + return sqrt(pow(E,2)); } void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) @@ -136,8 +136,8 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) double ans1 = 0.0; for(unsigned int i =0;i &Cg, vector < vector > &polyGrad, vector &wei) @@ -129,7 +99,7 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } for(unsigned int i=0;i &Cg) double res =0.0; for(unsigned int i=0;i > &polyGrad, for(int i = 0;i(i,j)= - power(red.at(i,j),r)*power(green.at(i,j),g)* - power(blue.at(i,j),b); + pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); @@ -515,8 +485,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*power(red.at(i,j),r)*power(green.at(i,j),g)* - power(blue.at(i,j),b); + (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* + pow(blue.at(i,j),b); kk=kk+1; } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 1f92d933be..b000e1a303 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -75,18 +75,6 @@ class Cloning void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final); }; -double power(double term, int p); - -double power(double term, int p) -{ - double res = 1.0; - for(int i=0;i(i,j*channel+c) = - sqrt(power(srx32.at(i,j*channel+c),2) + power(sry32.at(i,j*channel+c),2)); + sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); } for(int i=0;i < h; i++) @@ -750,9 +738,9 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph if(srx32.at(i,j*channel+c) != 0) { srx32.at(i,j*channel+c) = - power(alpha,beta)*srx32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); + pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); sry32.at(i,j*channel+c) = - power(alpha,beta)*sry32.at(i,j*channel+c)*power(mag.at(i,j*channel+c),-1*beta); + pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); } } From daa9694cab2299d0168505d7f781497f9978059f Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 7 Oct 2013 19:30:13 +0530 Subject: [PATCH 20/27] Changes done in decolorization module --- modules/photo/src/contrast_preserve.cpp | 46 ++---- modules/photo/src/contrast_preserve.hpp | 190 +++++++----------------- 2 files changed, 61 insertions(+), 175 deletions(-) diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index 56912199ea..c60e7184b9 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -51,13 +51,6 @@ using namespace std; using namespace cv; -double norm_m(double); - -double norm_m(double E) -{ - return sqrt(pow(E,2)); -} - void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) { Mat I = _src.getMat(); @@ -78,6 +71,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) return; } + // Parameter Setting int maxIter = 15; int iterCount = 0; double tol = .0001; @@ -91,11 +85,11 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) img = Mat(I.size(),CV_32FC3); I.convertTo(img,CV_32FC3,1.0/255.0); + // Initialization obj.init(); vector Cg; vector < vector > polyGrad; - vector < vector > bc; vector < vector < int > > comb; vector alf; @@ -103,6 +97,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) obj.grad_system(img,polyGrad,Cg,comb); obj.weak_order(img,alf); + // Solver Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); obj.wei_update_matrix(polyGrad,Cg,Mt); @@ -111,7 +106,7 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) //////////////////////////////// main loop starting //////////////////////////////////////// - while(norm_m(E-pre_E) > tol) + while(sqrt(pow(E-pre_E,2)) > tol) { iterCount +=1; pre_E = E; @@ -136,8 +131,8 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) double ans1 = 0.0; for(unsigned int i =0;i lab_channel; + split(lab,lab_channel); - for(int i =0;i(i,j) = lab.at(i,j*3+0); - a.at(i,j) = lab.at(i,j*3+1); - b.at(i,j) = lab.at(i,j*3+2); - } + dst.copyTo(lab_channel[0]); - for(int i =0;i(i,j) = dst.at(i,j); - } - - for(int i =0;i(i,j*3+0) = l.at(i,j); - lab.at(i,j*3+1) = a.at(i,j); - lab.at(i,j*3+2) = b.at(i,j); - } + merge(lab_channel,lab); cvtColor(lab,color_boost,COLOR_Lab2BGR); } diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 87e33a38c9..6319d15513 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -51,11 +51,12 @@ using namespace cv; class Decolor { private: - Mat kernel; - Mat kernel1; + Mat kernelx; + Mat kernely; int order; public: + float sigma; void init(); vector product(vector < vector > &comb, vector &initRGB); double energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei); @@ -73,18 +74,9 @@ class Decolor void grayImContruct(vector &wei, Mat img, Mat &Gray); }; -int rounding(double a); - -int rounding(double a) -{ - return int(a + 0.5); -} - -float sigma = .02; - double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) { - vector P; + vector energy; vector temp; vector temp1; @@ -99,11 +91,11 @@ double Decolor::energyCalcu(vector &Cg, vector < vector > &pol } for(unsigned int i=0;i &Cg, vector < vector > &pol void Decolor::init() { - kernel = Mat(1,2, CV_32FC1); - kernel1 = Mat(2,1, CV_32FC1); - kernel.at(0,0)=1.0; - kernel.at(0,1)=-1.0; - kernel1.at(0,0)=1.0; - kernel1.at(1,0)=-1.0; + kernelx = Mat(1,2, CV_32FC1); + kernely = Mat(2,1, CV_32FC1); + kernelx.at(0,0)=1.0; + kernelx.at(0,1)=-1.0; + kernely.at(0,0)=1.0; + kernely.at(1,0)=-1.0; order = 2; + sigma = .02; } vector Decolor::product(vector < vector > &comb, vector &initRGB) @@ -138,8 +131,8 @@ void Decolor::singleChannelGradx(const Mat &img, Mat& dest) { int w=img.size().width; int h=img.size().height; - Point anchor(kernel.cols - kernel.cols/2 - 1, kernel.rows - kernel.rows/2 - 1); - filter2D(img, dest, -1, kernel, anchor, 0.0, BORDER_CONSTANT); + 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; } @@ -148,8 +141,8 @@ void Decolor::singleChannelGrady(const Mat &img, Mat& dest) { int w=img.size().width; int h=img.size().height; - Point anchor(kernel1.cols - kernel1.cols/2 - 1, kernel1.rows - kernel1.rows/2 - 1); - filter2D(img, dest, -1, kernel1, anchor, 0.0, BORDER_CONSTANT); + 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; } @@ -182,25 +175,19 @@ void Decolor::colorGrad(Mat img, vector &Cg) { Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); cvtColor(img,lab,COLOR_BGR2Lab); - for(int i=0;i(i,j) = lab.at(i,j*3+0); - a_channel.at(i,j) = lab.at(i,j*3+1); - b_channel.at(i,j) = lab.at(i,j*3+2); - } + + vector lab_channel; + split(lab,lab_channel); vector ImL; vector Ima; vector Imb; - gradvector(l_channel,ImL); - gradvector(a_channel,Ima); - gradvector(b_channel,Imb); + + gradvector(lab_channel[0],ImL); + gradvector(lab_channel[1],Ima); + gradvector(lab_channel[2],Imb); double res =0.0; for(unsigned int i=0;i &Cg) res=sqrt(pow(ImL[i],2) + pow(Ima[i],2) + pow(Imb[i],2))/100; Cg.push_back(res); } - lab.release(); - l_channel.release(); - a_channel.release(); - b_channel.release(); ImL.clear(); Ima.clear(); @@ -245,37 +228,20 @@ void Decolor::weak_order(Mat img, vector &alf) if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); } Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + vector rgb_channel; + split(img,rgb_channel); - vector Rg; - vector Gg; - vector Bg; + vector Rg, Gg, Bg; + vector t1, t2, t3; + vector tmp1, tmp2, tmp3; - vector t1; - vector t2; - vector t3; - - vector tmp1; - vector tmp2; - vector tmp3; - - gradvector(red,Rg); - gradvector(green,Gg); - gradvector(blue,Bg); + gradvector(rgb_channel[2],Rg); + gradvector(rgb_channel[1],Gg); + gradvector(rgb_channel[0],Bg); double level = .05; @@ -285,37 +251,27 @@ void Decolor::weak_order(Mat img, vector &alf) t1.push_back(1.0); else t1.push_back(0.0); - } - for(unsigned int i=0;i level) t2.push_back(1.0); else t2.push_back(0.0); - } - for(unsigned int i=0;i level) t3.push_back(1.0); else t3.push_back(0.0); - } - for(unsigned int i=0;i &alf) sum = (double)100*sum/alf.size(); - red.release(); - green.release(); - blue.release(); - curIm.release(); - - Rg.clear(); - Gg.clear(); - Bg.clear(); - - t1.clear(); - t2.clear(); - t3.clear(); - - tmp1.clear(); - tmp2.clear(); - tmp3.clear(); + Rg.clear(); Gg.clear(); Bg.clear(); + t1.clear(); t2.clear(); t3.clear(); + tmp1.clear(); tmp2.clear(); tmp3.clear(); } void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, @@ -361,7 +304,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(rounding(h*sizefactor),rounding(w*sizefactor))); + resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); } h = img.size().height; @@ -369,17 +312,8 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, colorGrad(img,Cg); Mat curIm = Mat(img.size(),CV_32FC1); - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + vector rgb_channel; + split(img,rgb_channel); for(int r=0 ;r <=order; r++) for(int g=0; g<=order;g++) @@ -391,18 +325,13 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, for(int i = 0;i(i,j)= - pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + pow(rgb_channel[2].at(i,j),r)*pow(rgb_channel[1].at(i,j),g)* + pow(rgb_channel[0].at(i,j),b); vector curGrad; gradvector(curIm,curGrad); add_to_vector_poly(polyGrad,curGrad); } } - - red.release(); - green.release(); - blue.release(); - curIm.release(); } void Decolor::wei_update_matrix(vector < vector > &poly, vector &Cg, Mat &X) @@ -425,10 +354,6 @@ void Decolor::wei_update_matrix(vector < vector > &poly, vector > &comb, vector &wei) @@ -463,17 +388,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) int h=img.size().height; int w=img.size().width; - Mat red = Mat(img.size(),CV_32FC1); - Mat green = Mat(img.size(),CV_32FC1); - Mat blue = Mat(img.size(),CV_32FC1); - - for(int i=0;i(i,j) = img.at(i,j*3+2); - green.at(i,j) = img.at(i,j*3+1); - blue.at(i,j) = img.at(i,j*3+0); - } + vector rgb_channel; + split(img,rgb_channel); int kk =0; @@ -485,8 +401,8 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i = 0;i(i,j)=Gray.at(i,j) + - (float) wei[kk]*pow(red.at(i,j),r)*pow(green.at(i,j),g)* - pow(blue.at(i,j),b); + (float) 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; } @@ -496,7 +412,7 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i=0;i(i,j) < minval) minval = Gray.at(i,j); @@ -507,8 +423,4 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); - - red.release(); - green.release(); - blue.release(); } From 35d9ca6483bfb5f7f87d3e502f105655a4f31a7b Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 9 Oct 2013 21:49:57 +0530 Subject: [PATCH 21/27] Changes done in cloning module --- modules/photo/include/opencv2/photo.hpp | 4 +- modules/photo/src/contrast_preserve.cpp | 12 +- modules/photo/src/seamless_cloning.cpp | 43 +- modules/photo/src/seamless_cloning.hpp | 654 ++++++++---------------- 4 files changed, 218 insertions(+), 495 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 1e83608800..256366afad 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -313,8 +313,8 @@ CV_EXPORTS_W Ptr createMergeRobertson(); float alpha = 0.2, float beta = 0.4); CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold, double high_threshold, - int kernel_size); + double low_threshold = 30, double high_threshold = 45, + int kernel_size = 3); CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp index c60e7184b9..7794b3646d 100644 --- a/modules/photo/src/contrast_preserve.cpp +++ b/modules/photo/src/contrast_preserve.cpp @@ -127,14 +127,14 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost) temp1.push_back(val + Cg[i]); } - double ans = 0.0; - double ans1 = 0.0; + double pos = 0.0; + double neg = 0.0; for(unsigned int i =0;i EXPsum; diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index b00a7bf379..c49f4a27bb 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -41,6 +41,7 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" +#include "opencv2/highgui.hpp" #include #include @@ -148,19 +149,7 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - int channel = 3; - for(int i=0;i(i,j) == 255) - { - for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); - } - } - - } + src.copyTo(cs_mask,gray); Cloning obj; obj.local_color_change(src,cs_mask,gray,blend,red,green,blue); @@ -186,19 +175,7 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - int channel = 3; - for(int i=0;i(i,j) == 255) - { - for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); - } - } - - } + src.copyTo(cs_mask,gray); Cloning obj; obj.illum_change(src,cs_mask,gray,blend,alpha,beta); @@ -223,19 +200,7 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); - int channel = 3; - for(int i=0;i(i,j) == 255) - { - for(int c=0;c(i,j*channel+c) = src.at(i,j*channel+c); - } - } - - } + src.copyTo(cs_mask,gray); Cloning obj; obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend); diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index b000e1a303..90bd2e4767 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -49,30 +49,32 @@ using namespace std; using namespace cv; -#define pi 3.1416 - class Cloning { public: - Mat grx,gry,sgx,sgy,r_channel,g_channel,b_channel,smask1,grx32,gry32; - Mat smask,srx32,sry32; - Mat rx_channel,ry_channel,gx_channel,gy_channel,bx_channel,by_channel,resultr,resultg,resultb; - void init(Mat &I, Mat &wmask); - void calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + vector rgb_channel, rgbx_channel, rgby_channel, output; + Mat grx, gry, sgx, sgy, srx32, sry32, grx32, gry32, smask, smask1; + void init_var(Mat &I, Mat &wmask); + void initialization(Mat &I, Mat &mask, Mat &wmask); + void scalar_product(Mat mat, float r, float g, float b); + void array_product(Mat mat1, Mat mat2, Mat mat3); + void poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy); + void evaluate(Mat &I, Mat &wmask, Mat &cloned); void getGradientx(const Mat &img, Mat &gx); void getGradienty(const Mat &img, Mat &gy); void lapx(const Mat &img, Mat &gxx); void lapy(const Mat &img, Mat &gyy); - void dst(double *gtest, double *gfinal,int h,int w); - void idst(double *gtest, double *gfinal,int h,int w); + void dst(double *mod_diff, double *sineTransform,int h,int w); + void idst(double *mod_diff, double *sineTransform,int h,int w); void transpose(double *mat, double *mat_t,int h,int w); + void solve(const Mat &img, double *mod_diff, Mat &result); void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); - void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num); - void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul, float green_mul, float blue_mul); - void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta); - void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final); + void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num); + void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul, float green_mul, float blue_mul); + void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta); + void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &cloned); }; void Cloning::getGradientx( const Mat &img, Mat &gx) @@ -80,8 +82,6 @@ void Cloning::getGradientx( const Mat &img, Mat &gx) int w = img.size().width; int h = img.size().height; int channel = img.channels(); - - gx = Mat::zeros(img.size(),CV_32FC3); for(int i=0;i(i,j*channel+c) = (float)img.at(i,(j+1)*channel+c) - (float)img.at(i,j*channel+c); } + } void Cloning::getGradienty( const Mat &img, Mat &gy) @@ -96,8 +97,6 @@ void Cloning::getGradienty( const Mat &img, Mat &gy) int w = img.size().width; int h = img.size().height; int channel = img.channels(); - - gy = Mat::zeros(img.size(),CV_32FC3); for(int i=0;i(temp), Mat::zeros(temp.size(), CV_32F)}; - Mat complex1; + Mat result; int p=0; for(int i=0;i(r,0) = (float) gtest[idx]; + temp.at(r,0) = (float) mod_diff[idx]; } temp.at(h+1,0)=0.0; @@ -167,54 +163,49 @@ void Cloning::dst(double *gtest, double *gfinal,int h,int w) for(int j=h-1, r=h+2;j>=0;j--,r++) { idx = j*w+i; - temp.at(r,0) = (float) (-1.0 * gtest[idx]); + temp.at(r,0) = (float) (-1.0 * mod_diff[idx]); } - merge(planes, 2, complex1); + merge(planes, 2, result); - dft(complex1,complex1,0,0); + dft(result,result,0,0); - Mat planes1[] = {Mat::zeros(complex1.size(), CV_32F), Mat::zeros(complex1.size(), CV_32F)}; + Mat planes1[] = {Mat::zeros(result.size(), CV_32F), Mat::zeros(result.size(), CV_32F)}; - split(complex1, planes1); + split(result, planes1); std::complex two_i = std::sqrt(std::complex(-1)); - double fac = -2*imag(two_i); + double factor = -2*imag(two_i); for(int c=1,z=0;c(z,0) = (float) (planes1[1].at(c,0)/fac); + res.at(z,0) = (float) (planes1[1].at(c,0)/factor); } for(int q=0,z=0;q(z,0); + sineTransform[idx] = res.at(z,0); } p++; } - - temp.release(); - res.release(); - planes[0].release(); - planes[1].release(); - } -void Cloning::idst(double *gtest, double *gfinal,int h,int w) +void Cloning::idst(double *mod_diff, double *sineTransform,int h,int w) { int nn = h+1; unsigned long int idx; - dst(gtest,gfinal,h,w); + dst(mod_diff,sineTransform,h,w); for(int i= 0;i(i,j); } - - tmp.release(); - } -void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) +void Cloning::solve(const Mat &img, double *mod_diff, Mat &result) { - int w = img.size().width; int h = img.size().height; unsigned long int idx,idx1; - Mat lap = Mat(img.size(),CV_32FC1); - - for(int i =0;i(i,j)=gyy.at(i,j)+gxx.at(i,j); - - Mat bound = img.clone(); - - for(int i =1;i(i,j) = 0; - } - - double *f_bp = new double[h*w]; - - - for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) - + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); - } - - Mat diff = Mat(h,w,CV_32FC1); - for(int i =0;i(i,j) = (float) (lap.at(i,j) - f_bp[idx]); - } - } - - lap.release(); - - double *gtest = new double[(h-2)*(w-2)]; - for(int i = 0 ; i < h-2;i++) - { - for(int j = 0 ; j < w-2; j++) - { - idx = i*(w-2) + j; - gtest[idx] = diff.at(i+1,j+1); - - } - } - - diff.release(); - ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// - - double *gfinal = new double[(h-2)*(w-2)]; - double *gfinal_t = new double[(h-2)*(w-2)]; + double *sineTransform = new double[(h-2)*(w-2)]; + double *sineTransform_t = new double[(h-2)*(w-2)]; double *denom = new double[(h-2)*(w-2)]; - double *f3 = new double[(h-2)*(w-2)]; - double *f3_t = new double[(h-2)*(w-2)]; + double *invsineTransform = new double[(h-2)*(w-2)]; + double *invsineTransform_t = new double[(h-2)*(w-2)]; double *img_d = new double[(h)*(w)]; - dst(gtest,gfinal,h-2,w-2); + dst(mod_diff,sineTransform,h-2,w-2); - transpose(gfinal,gfinal_t,h-2,w-2); + transpose(sineTransform,sineTransform_t,h-2,w-2); - dst(gfinal_t,gfinal,w-2,h-2); + dst(sineTransform_t,sineTransform,w-2,h-2); - transpose(gfinal,gfinal_t,w-2,h-2); + transpose(sineTransform,sineTransform_t,w-2,h-2); - int cy=1; + int cy = 1; for(int i = 0 ; i < w-2;i++,cy++) { for(int j = 0,cx = 1; j < h-2; j++,cx++) { idx = j*(w-2) + i; - denom[idx] = (float) 2*cos(pi*cy/( (double) (w-1))) - 2 + 2*cos(pi*cx/((double) (h-1))) - 2; + denom[idx] = (float) 2*cos(CV_PI*cy/( (double) (w-1))) - 2 + 2*cos(CV_PI*cx/((double) (h-1))) - 2; } } for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++) { - gfinal_t[idx] = gfinal_t[idx]/denom[idx]; + sineTransform_t[idx] = sineTransform_t[idx]/denom[idx]; } - idst(gfinal_t,f3,h-2,w-2); + idst(sineTransform_t,invsineTransform,h-2,w-2); - transpose(f3,f3_t,h-2,w-2); + transpose(invsineTransform,invsineTransform_t,h-2,w-2); - idst(f3_t,f3,w-2,h-2); + idst(invsineTransform_t,invsineTransform,w-2,h-2); - transpose(f3,f3_t,w-2,h-2); + transpose(invsineTransform,invsineTransform_t,w-2,h-2); for(int i = 0 ; i < h;i++) { @@ -363,7 +299,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { idx = i*w + j; idx1= id1*(w-2) + id2; - img_d[idx] = f3_t[idx1]; + img_d[idx] = invsineTransform_t[idx1]; } } @@ -381,35 +317,76 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) } } - delete [] gfinal; - delete [] gfinal_t; + delete [] sineTransform; + delete [] sineTransform_t; delete [] denom; - delete [] f3; - delete [] f3_t; + delete [] invsineTransform; + delete [] invsineTransform_t; delete [] img_d; - delete [] gtest; - delete [] f_bp; } -void Cloning::init(Mat &I, Mat &wmask) +void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) { + int w = img.size().width; + int h = img.size().height; + + unsigned long int idx; + + Mat lap = Mat(img.size(),CV_32FC1); + + lap = gxx + gyy; + + Mat bound = img.clone(); + + rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1); + + double *boundary_point = new double[h*w]; + + for(int i =1;i(i,j) + (int)bound.at(i,(j+1)) + (int)bound.at(i,(j-1)) + + (int)bound.at(i-1,j) + (int)bound.at(i+1,j); + } + + Mat diff = Mat(h,w,CV_32FC1); + for(int i =0;i(i,j) = (float) (lap.at(i,j) - boundary_point[idx]); + } + } + + double *mod_diff = new double[(h-2)*(w-2)]; + for(int i = 0 ; i < h-2;i++) + { + for(int j = 0 ; j < w-2; j++) + { + idx = i*(w-2) + j; + mod_diff[idx] = diff.at(i+1,j+1); + + } + } + ///////////////////////////////////////////////////// Find DST ///////////////////////////////////////////////////// + + solve(img,mod_diff,result); + + delete [] mod_diff; + delete [] boundary_point; +} + +void Cloning::init_var(Mat &I, Mat &wmask) +{ grx = Mat(I.size(),CV_32FC3); gry = Mat(I.size(),CV_32FC3); sgx = Mat(I.size(),CV_32FC3); sgy = Mat(I.size(),CV_32FC3); - r_channel = Mat::zeros(I.size(),CV_8UC1); - g_channel = Mat::zeros(I.size(),CV_8UC1); - b_channel = Mat::zeros(I.size(),CV_8UC1); - - for(int i=0;i(i,j) = I.at(i,j*3+0); - g_channel.at(i,j) = I.at(i,j*3+1); - b_channel.at(i,j) = I.at(i,j*3+2); - } + split(I,rgb_channel); smask = Mat(wmask.size(),CV_32FC1); srx32 = Mat(I.size(),CV_32FC3); @@ -419,22 +396,55 @@ void Cloning::init(Mat &I, Mat &wmask) gry32 = Mat(I.size(),CV_32FC3); } -void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) +void Cloning::initialization(Mat &I, Mat &mask, Mat &wmask) { + init_var(I,wmask); - int channel = I.channels(); + getGradientx(I,grx); + getGradienty(I,gry); + + getGradientx(mask,sgx); + getGradienty(mask,sgy); + + Mat Kernel(Size(3, 3), CV_8UC1); + Kernel.setTo(Scalar(1)); + + erode(wmask, wmask, Kernel, Point(-1,-1), 3); + + wmask.convertTo(smask,CV_32FC1,1.0/255.0); + I.convertTo(srx32,CV_32FC3,1.0/255.0); + I.convertTo(sry32,CV_32FC3,1.0/255.0); +} + +void Cloning::scalar_product(Mat mat, float r, float g, float b) +{ + vector channels; + split(mat,channels); + multiply(channels[2],r,channels[2]); + multiply(channels[1],g,channels[1]); + multiply(channels[0],b,channels[0]); + merge(channels,mat); +} + +void Cloning::array_product(Mat mat1, Mat mat2, Mat mat3) +{ + vector channels_temp1; + vector channels_temp2; + split(mat1,channels_temp1); + split(mat2,channels_temp2); + multiply(channels_temp2[2],mat3,channels_temp1[2]); + multiply(channels_temp2[1],mat3,channels_temp1[1]); + multiply(channels_temp2[0],mat3,channels_temp1[0]); + merge(channels_temp1,mat1); +} + +void Cloning::poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) +{ Mat fx = Mat(I.size(),CV_32FC3); Mat fy = Mat(I.size(),CV_32FC3); - for(int i=0;i < I.size().height; i++) - for(int j=0; j < I.size().width; j++) - for(int c=0;c(i,j*channel+c) = - (gx.at(i,j*channel+c)+sx.at(i,j*channel+c)); - fy.at(i,j*channel+c) = - (gy.at(i,j*channel+c)+sy.at(i,j*channel+c)); - } + fx = gx + sx; + fy = gy + sy; Mat gxx = Mat(I.size(),CV_32FC3); Mat gyy = Mat(I.size(),CV_32FC3); @@ -442,79 +452,44 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy) lapx(fx,gxx); lapy(fy,gyy); - rx_channel = Mat(I.size(),CV_32FC1); - gx_channel = Mat(I.size(),CV_32FC1); - bx_channel = Mat(I.size(),CV_32FC1); + split(gxx,rgbx_channel); + split(gyy,rgby_channel); - for(int i=0;i(i,j) = gxx.at(i,j*3+0); - gx_channel.at(i,j) = gxx.at(i,j*3+1); - bx_channel.at(i,j) = gxx.at(i,j*3+2); - } + split(I,output); - ry_channel = Mat(I.size(),CV_32FC1); - gy_channel = Mat(I.size(),CV_32FC1); - by_channel = Mat(I.size(),CV_32FC1); + poisson_solver(rgb_channel[2],rgbx_channel[2], rgby_channel[2],output[2]); + poisson_solver(rgb_channel[1],rgbx_channel[1], rgby_channel[1],output[1]); + poisson_solver(rgb_channel[0],rgbx_channel[0], rgby_channel[0],output[0]); +} - for(int i=0;i(i,j) = gyy.at(i,j*3+0); - gy_channel.at(i,j) = gyy.at(i,j*3+1); - by_channel.at(i,j) = gyy.at(i,j*3+2); - } +void Cloning::evaluate(Mat &I, Mat &wmask, Mat &cloned) +{ + bitwise_not(wmask,wmask); - resultr = Mat(I.size(),CV_8UC1); - resultg = Mat(I.size(),CV_8UC1); - resultb = Mat(I.size(),CV_8UC1); + wmask.convertTo(smask1,CV_32FC1,1.0/255.0); + I.convertTo(grx32,CV_32FC3,1.0/255.0); + I.convertTo(gry32,CV_32FC3,1.0/255.0); - poisson_solver(r_channel,rx_channel, ry_channel,resultr); - poisson_solver(g_channel,gx_channel, gy_channel,resultg); - poisson_solver(b_channel,bx_channel, by_channel,resultb); + array_product(grx32,grx,smask1); + array_product(gry32,gry,smask1); + poisson(I,grx32,gry32,srx32,sry32); + + merge(output,cloned); } -void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) +void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num) { - init(I,wmask); - int w = I.size().width; int h = I.size().height; int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); - - if(num != 3) - { - getGradientx(mask,sgx); - getGradienty(mask,sgy); - } - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); + initialization(I,mask,wmask); if(num == 1) { - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); } else if(num == 2) @@ -546,194 +521,53 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num) Mat gray = Mat(mask.size(),CV_8UC1); Mat gray8 = Mat(mask.size(),CV_8UC3); cvtColor(mask, gray, COLOR_BGR2GRAY ); + vector temp; + split(I,temp); + gray.copyTo(temp[2]); + gray.copyTo(temp[1]); + gray.copyTo(temp[0]); - for(int i=0;i(i,j*3+0) = gray.at(i,j); - gray8.at(i,j*3+1) = gray.at(i,j); - gray8.at(i,j*3+2) = gray.at(i,j); - } - + merge(temp,gray8); getGradientx(gray8,sgx); getGradienty(gray8,sgy); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); } - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } - + evaluate(I,wmask,cloned); } -void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul=1.0, +void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul=1.0, float green_mul=1.0, float blue_mul=1.0) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; - int channel = I.channels(); - - getGradientx(I,grx); - getGradienty(I,gry); + initialization(I,mask,wmask); - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } - - Mat factor = Mat(I.size(),CV_32FC3); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - { - factor.at(i,j*channel+0) = blue_mul; - factor.at(i,j*channel+1) = green_mul; - factor.at(i,j*channel+2) = red_mul; - } - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - srx32.at(i,j*channel+c)*factor.at(i,j*channel+c); - sry32.at(i,j*channel+c) = - sry32.at(i,j*channel+c)*factor.at(i,j*channel+c); - } - - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); + scalar_product(srx32,red_mul,green_mul,blue_mul); + scalar_product(sry32,red_mul,green_mul,blue_mul); + evaluate(I,wmask,cloned); } -void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta) +void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; int channel = I.channels(); - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); - } + initialization(I,mask,wmask); + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); Mat mag = Mat(I.size(),CV_32FC3); - I.convertTo(mag,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - sqrt(pow(srx32.at(i,j*channel+c),2) + pow(sry32.at(i,j*channel+c),2)); - } + magnitude(srx32,sry32,mag); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) != 0) { @@ -744,108 +578,32 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph } } - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + evaluate(I,wmask,cloned); } - void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, - double high_threshold, int kernel_size, Mat &final) + double high_threshold, int kernel_size, Mat &cloned) { - init(I,wmask); - - int w = I.size().width; - int h = I.size().height; - - getGradientx(I,grx); - getGradienty(I,gry); - - getGradientx(mask,sgx); - getGradienty(mask,sgy); - - Mat Kernel(Size(3, 3), CV_8UC1); - Kernel.setTo(Scalar(1)); - - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); - erode(wmask, wmask, Kernel); + int channel = mask.channels(); - wmask.convertTo(smask,CV_32FC1,1.0/255.0); - I.convertTo(srx32,CV_32FC3,1.0/255.0); - I.convertTo(sry32,CV_32FC3,1.0/255.0); + initialization(I,mask,wmask); Mat out = Mat(mask.size(),CV_8UC1); Canny(mask,out,low_threshold,high_threshold,kernel_size); - int channel = mask.channels(); - for(int i=0;i(i,j) != 255) - { + { sgx.at(i,j*channel+c) = 0.0; sgy.at(i,j*channel+c) = 0.0; - } - } - - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (sgx.at(i,j*channel+c)*smask.at(i,j)); - sry32.at(i,j*channel+c) = - (sgy.at(i,j*channel+c)*smask.at(i,j)); + } } - bitwise_not(wmask,wmask); - - wmask.convertTo(smask1,CV_32FC1,1.0/255.0); - I.convertTo(grx32,CV_32FC3,1.0/255.0); - I.convertTo(gry32,CV_32FC3,1.0/255.0); + array_product(srx32,sgx,smask); + array_product(sry32,sgy,smask); - for(int i=0;i < h; i++) - for(int j=0; j < w; j++) - for(int c=0;c(i,j*channel+c) = - (grx.at(i,j*channel+c)*smask1.at(i,j)); - gry32.at(i,j*channel+c) = - (gry.at(i,j*channel+c)*smask1.at(i,j)); - } - - calc(I,grx32,gry32,srx32,sry32); - - for(int i=0;i(i,j*3+0) = resultr.at(i,j); - final.at(i,j*3+1) = resultg.at(i,j); - final.at(i,j*3+2) = resultb.at(i,j); - } + evaluate(I,wmask,cloned); } From 2f65a0d4bab9c38854042a7e64814c59240f2f29 Mon Sep 17 00:00:00 2001 From: siddharth Date: Thu, 17 Oct 2013 21:14:31 +0530 Subject: [PATCH 22/27] Changes done in npr module --- modules/photo/src/npr.cpp | 99 +++------------ modules/photo/src/npr.hpp | 162 ++++++++----------------- modules/photo/src/seamless_cloning.cpp | 30 ++--- modules/photo/src/seamless_cloning.hpp | 45 +++---- 4 files changed, 95 insertions(+), 241 deletions(-) diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index 08c7753410..a3b38d4ee1 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -79,34 +79,24 @@ void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float s int h = I.size().height; int w = I.size().width; - int channel = I.channels(); float factor = 3.0; Mat img = Mat(I.size(),CV_32FC3); I.convertTo(img,CV_32FC3,1.0/255.0); - Mat res = Mat(h,w,CV_32FC3); + Mat res = Mat(h,w,CV_32FC1); dst.convertTo(res,CV_32FC3,1.0/255.0); Mat result = Mat(img.size(),CV_32FC3); Mat lab = Mat(img.size(),CV_32FC3); - Mat l_channel = Mat(img.size(),CV_32FC1); - Mat a_channel = Mat(img.size(),CV_32FC1); - Mat b_channel = Mat(img.size(),CV_32FC1); + vector lab_channel; cvtColor(img,lab,COLOR_BGR2Lab); - - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - l_channel.at(i,j) = lab.at(i,j*channel+0); - a_channel.at(i,j) = lab.at(i,j*channel+1); - b_channel.at(i,j) = lab.at(i,j*channel+2); - } + split(lab,lab_channel); Mat L = Mat(img.size(),CV_32FC1); - l_channel.convertTo(L,CV_32FC1,1.0/255.0); + lab_channel[0].convertTo(L,CV_32FC1,1.0/255.0); Domain_Filter obj; @@ -114,23 +104,13 @@ void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float s Mat detail = Mat(h,w,CV_32FC1); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - detail.at(i,j) = L.at(i,j) - res.at(i,j); - - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - L.at(i,j) = res.at(i,j) + factor*detail.at(i,j); + detail = L - res; + multiply(detail,factor,detail); + L = res + detail; - L.convertTo(l_channel,CV_32FC1,255); + L.convertTo(lab_channel[0],CV_32FC1,255); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - lab.at(i,j*channel+0) = l_channel.at(i,j); - lab.at(i,j*channel+1) = a_channel.at(i,j); - lab.at(i,j*channel+2) = b_channel.at(i,j); - } + merge(lab_channel,lab); cvtColor(lab,result,COLOR_Lab2BGR); result.convertTo(dst,CV_8UC3,255); @@ -174,64 +154,21 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig int channel = img.channels(); Mat res = Mat(h,w,CV_32FC3); + Mat magnitude = Mat(h,w,CV_32FC1); Domain_Filter obj; obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - vector planes; - split(res, planes); - - Mat magXR = Mat(h, w, CV_32FC1); - Mat magYR = Mat(h, w, CV_32FC1); - - Mat magXG = Mat(h, w, CV_32FC1); - Mat magYG = Mat(h, w, CV_32FC1); - - Mat magXB = Mat(h, w, CV_32FC1); - Mat magYB = Mat(h, w, CV_32FC1); - - Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); - Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - - Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); - Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - - Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); - Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); - - Mat magx = Mat(h,w,CV_32FC1); - Mat magy = Mat(h,w,CV_32FC1); - - Mat mag1 = Mat(h,w,CV_32FC1); - Mat mag2 = Mat(h,w,CV_32FC1); - Mat mag3 = Mat(h,w,CV_32FC1); - - magnitude(magXR,magYR,mag1); - magnitude(magXG,magYG,mag2); - magnitude(magXB,magYB,mag3); - - Mat magnitude = Mat(h,w,CV_32FC1); - - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); - } - - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = 1.0f - magnitude.at(i,j); - } + obj.find_magnitude(res,magnitude,2); Mat stylized = Mat(h,w,CV_32FC3); - for(int i =0;i < h;i++) - for(int j=0;j(i,j*channel + c) = res.at(i,j*channel + c) * magnitude.at(i,j); - } + vector temp; + split(res,temp); + multiply(temp[0],magnitude,temp[0]); + multiply(temp[1],magnitude,temp[1]); + multiply(temp[2],magnitude,temp[2]); + merge(temp,stylized); stylized.convertTo(dst,CV_8UC3,255); } @@ -259,7 +196,7 @@ void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sig obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - obj.find_magnitude(res,magnitude); + obj.find_magnitude(res,magnitude,1); magnitude.convertTo(dst,CV_8UC1,255); } diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 3f5519d1bb..733d418d58 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -61,7 +61,7 @@ class Domain_Filter void getGradienty( const Mat &img, Mat &gy); void diffx(const Mat &img, Mat &temp); void diffy(const Mat &img, Mat &temp); - void find_magnitude(Mat &img, Mat &mag); + void find_magnitude(Mat &img, Mat &mag, int flags); void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); @@ -131,9 +131,8 @@ void Domain_Filter::getGradienty( const Mat &img, Mat &gy) } } -void Domain_Filter::find_magnitude(Mat &img, Mat &mag) +void Domain_Filter::find_magnitude(Mat &img, Mat &mag, int flags) { - int h = img.rows; int w = img.cols; @@ -149,17 +148,28 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag) Mat magXB = Mat(h, w, CV_32FC1); Mat magYB = Mat(h, w, CV_32FC1); - getGradientx(planes[0], magXR); - getGradienty(planes[0], magYR); + if(flags == 1) + { + getGradientx(planes[0], magXR); + getGradienty(planes[0], magYR); + + getGradientx(planes[1], magXG); + getGradienty(planes[1], magYG); - getGradientx(planes[1], magXG); - getGradienty(planes[1], magYG); + getGradientx(planes[2], magXR); + getGradienty(planes[2], magYR); + } + else if(flags == 2) + { + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - getGradientx(planes[2], magXR); - getGradienty(planes[2], magYR); + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - Mat magx = Mat(h,w,CV_32FC1); - Mat magy = Mat(h,w,CV_32FC1); + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); + } Mat mag1 = Mat(h,w,CV_32FC1); Mat mag2 = Mat(h,w,CV_32FC1); @@ -169,39 +179,21 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag) magnitude(magXG,magYG,mag2); magnitude(magXB,magYB,mag3); - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = mag1.at(i,j) + mag2.at(i,j) + mag3.at(i,j); - } - - - for(int i =0;i < h;i++) - for(int j=0;j(i,j) = 1.0f - mag.at(i,j); - } - + mag = mag1 + mag2 + mag3; + mag = 1.0f - mag; } void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { - - float a; - int h = output.rows; int w = output.cols; int channel = output.channels(); - a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); + float a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); Mat temp = Mat(h,w,CV_32FC3); - for(int i =0; i < h;i++) - for(int j=0;j(i,j*channel+c) = output.at(i,j*channel+c); - + output.copyTo(temp); Mat V = Mat(h,w,CV_32FC1); for(int i=0;i(i,j*channel+c) = temp.at(i,j*channel+c); - - temp.release(); - V.release(); + temp.copyTo(output); } void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius) @@ -249,12 +234,8 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float Mat lower_pos = Mat(h,w,CV_32FC1); Mat upper_pos = Mat(h,w,CV_32FC1); - for(int i=0;i(i,j) = hz.at(i,j) - radius; - upper_pos.at(i,j) = hz.at(i,j) + radius; - } + lower_pos = hz - radius; + upper_pos = hz + radius; lower_idx = Mat::zeros(h,w,CV_32FC1); upper_idx = Mat::zeros(h,w,CV_32FC1); @@ -334,19 +315,11 @@ void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float upper_idx.at(i,j) = temp_upper_idx.at(0,j) + 1; } - lower_pos_row.release(); - upper_pos_row.release(); - temp_lower_idx.release(); - temp_upper_idx.release(); } - for(int i=0;i(i,j) = upper_idx.at(i,j) - lower_idx.at(i,j); - + psketch = upper_idx - lower_idx; } void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius) { - int h = output.rows; int w = output.cols; int channel = output.channels(); @@ -377,24 +350,25 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r Mat a = Mat::zeros(h,w,CV_32FC1); Mat b = Mat::zeros(h,w,CV_32FC1); + // Compute the box filter using a summed area table. for(int c=0;c(i,j) = (c+1)*flag.at(i,j); + multiply(flag,c+1,flag); - for(int i=0;i(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (lower_idx.at(i,j) - 1) * h + indices.at(i,j); - b.at(i,j) = (flag.at(i,j) - 1) * h * (w+1) + (upper_idx.at(i,j) - 1) * h + indices.at(i,j); + Mat temp1, temp2; + multiply(flag - 1,h*(w+1),temp1); + multiply(lower_idx - 1,h,temp2); + a = temp1 + temp2 + indices; - } + multiply(flag - 1,h*(w+1),temp1); + multiply(upper_idx - 1,h,temp2); + b = temp1 + temp2 + indices; int p,q,r,rem; int p1,q1,r1,rem1; + // Calculating indices for(int i=0;i(i,j)/(h*(w+1)); rem1 = (int) a.at(i,j) - r1*h*(w+1); q1 = rem1/h; @@ -427,18 +400,13 @@ void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float r q1=q1-1; } - final.at(i,j*channel+2-c) = (box_filter.at(p-1,q*channel+(2-r)) - box_filter.at(p1-1,q1*channel+(2-r1))) /(upper_idx.at(i,j) - lower_idx.at(i,j)); } } } - for(int i=0;i(i,j*channel+c) = final.at(i,j*channel+c); - + final.copyTo(output); } void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r) { @@ -482,20 +450,15 @@ void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r Mat final = Mat(h,w,CV_32FC3); - for(int i = 0; i < h; i++) - for(int j = 0; j < w; j++) - { - horiz.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at(i,j); - vert.at(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at(i,j); - } + Mat tempx,tempy; + multiply(distx,sigma_s/sigma_r,tempx); + multiply(disty,sigma_s/sigma_r,tempy); + horiz = 1.0f + tempx; + vert = 1.0f + tempy; O = Mat(h,w,CV_32FC3); - - for(int i =0;i(i,j*channel+c) = img.at(i,j*channel+c); + img.copyTo(O); O_t = Mat(w,h,CV_32FC3); @@ -588,17 +551,14 @@ void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, f init(img,2,sigma_s,sigma_r); int h = img.size().height; int w = img.size().width; - int channel = img.channels(); /////////////////////// convert to YCBCR model for color pencil drawing ////////////////////////////////////////////////////// Mat color_sketch = Mat(h,w,CV_32FC3); - Mat Y_channel = Mat(h,w,CV_32FC1); - Mat U_channel = Mat(h,w,CV_32FC1); - Mat V_channel = Mat(h,w,CV_32FC1); cvtColor(img,color_sketch,COLOR_BGR2YCrCb); + vector YUV_channel; Mat vert_t = ct_V.t(); float sigma_h = sigma_s; @@ -635,33 +595,11 @@ void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, f if(i==0) { sketch = pen_res.clone(); - - for(int k = 0; k < h; k++) - for(int j = 0; j < w; j++) - { - Y_channel.at(k,j) = color_sketch.at(k,j*channel+0); - U_channel.at(k,j) = color_sketch.at(k,j*channel+1); - V_channel.at(k,j) = color_sketch.at(k,j*channel+2); - } - - - for(int k=0;k(k,j) = pen_res.at(k,j); - - // cvMerge(Y_channel,U_channel,V_channel,0,color_sketch); - for(int k = 0; k < h; k++) - for(int j = 0; j < w; j++) - { - color_sketch.at(k,j*channel+0) = Y_channel.at(k,j); - color_sketch.at(k,j*channel+1) = U_channel.at(k,j); - color_sketch.at(k,j*channel+2) = V_channel.at(k,j); - } - + split(color_sketch,YUV_channel); + pen_res.copyTo(YUV_channel[0]); + merge(YUV_channel,color_sketch); cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR); - } } - } diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp index c49f4a27bb..63f4530477 100644 --- a/modules/photo/src/seamless_cloning.cpp +++ b/modules/photo/src/seamless_cloning.cpp @@ -41,7 +41,6 @@ #include "precomp.hpp" #include "opencv2/photo.hpp" -#include "opencv2/highgui.hpp" #include #include @@ -100,30 +99,17 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point exit(0); } - for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) - for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) - { - dst_mask.at(k,l) = gray.at(i,j); - } + Rect roi_d(minyd,minxd,leny,lenx); + Rect roi_s(miny,minx,leny,lenx); - int channel = 3; + Mat destinationROI = dst_mask(roi_d); + Mat sourceROI = cs_mask(roi_s); - for(int i=minx;i<(minx+lenx);i++) - for(int j=miny;j<(miny+leny);j++) - { - for(int c=0;c<3;c++) - { - if(gray.at(i,j) == 255) - cs_mask.at(i,j*channel+c) = src.at(i,j*channel+c); - } - } + gray(roi_s).copyTo(destinationROI); + src(roi_s).copyTo(sourceROI,gray(roi_s)); - for(int i=minx, k=minxd;i<(minx+lenx);i++,k++) - for(int j=miny,l=minyd ;j<(miny+leny);j++,l++) - { - for(int c=0;c(k,l*channel+c) = cs_mask.at(i,j*channel+c); - } + destinationROI = cd_mask(roi_d); + cs_mask(roi_s).copyTo(destinationROI); Cloning obj; obj.normal_clone(dest,cd_mask,dst_mask,blend,flags); diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 90bd2e4767..612d764d95 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -555,8 +555,6 @@ void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, flo void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta) { - int channel = I.channels(); - initialization(I,mask,wmask); array_product(srx32,sgx,smask); @@ -565,18 +563,20 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alp Mat mag = Mat(I.size(),CV_32FC3); magnitude(srx32,sry32,mag); - for(int i=0;i < I.size().height; i++) - for(int j=0; j < I.size().width; j++) - for(int c=0;c < channel;++c) - { - if(srx32.at(i,j*channel+c) != 0) - { - srx32.at(i,j*channel+c) = - pow(alpha,beta)*srx32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - sry32.at(i,j*channel+c) = - pow(alpha,beta)*sry32.at(i,j*channel+c)*pow(mag.at(i,j*channel+c),-1*beta); - } - } + Mat multX, multY, multx_temp, multy_temp; + + multiply(srx32,pow(alpha,beta),multX); + pow(mag,-1*beta, multx_temp); + multiply(multX,multx_temp,srx32); + + multiply(sry32,pow(alpha,beta),multY); + pow(mag,-1*beta, multy_temp); + multiply(multY,multy_temp,sry32); + + Mat zeroMask = (srx32 != 0); + + srx32.copyTo(srx32, zeroMask); + sry32.copyTo(sry32, zeroMask); evaluate(I,wmask,cloned); } @@ -584,23 +584,16 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alp void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threshold, int kernel_size, Mat &cloned) { - int channel = mask.channels(); - initialization(I,mask,wmask); Mat out = Mat(mask.size(),CV_8UC1); Canny(mask,out,low_threshold,high_threshold,kernel_size); - for(int i=0;i(i,j) != 255) - { - sgx.at(i,j*channel+c) = 0.0; - sgy.at(i,j*channel+c) = 0.0; - } - } + Mat zeros(sgx.size(), CV_32FC3); + zeros.setTo(0); + Mat zerosMask = (out != 255); + zeros.copyTo(sgx, zerosMask); + zeros.copyTo(sgy, zerosMask); array_product(srx32,sgx,smask); array_product(sry32,sgy,smask); From 33e6c074855c8d84e28fff8e3158a33bf17be800 Mon Sep 17 00:00:00 2001 From: siddharth Date: Mon, 21 Oct 2013 19:54:32 +0530 Subject: [PATCH 23/27] Removed build errors and removed test images Removed conflict Error fix 1 Error fix 2 Error fix 3 Error fix 3 Error fix 4 Error fix 5 Error fix 6 Error fix 7 Error fix 8 Error fix 9 Error fix 10 Error fix 11 Error fix 12 Errors fixed Removed opencv_extra folder inside opencv folder --- modules/photo/doc/cloning.rst | 2 +- modules/photo/doc/npr.rst | 15 -- modules/photo/include/opencv2/photo.hpp | 303 ++++++++++++------------ modules/photo/src/contrast_preserve.hpp | 11 +- modules/photo/src/npr.cpp | 31 +-- modules/photo/src/npr.hpp | 30 +-- modules/photo/test/test_npr.cpp | 16 -- samples/cpp/cloning_demo.cpp | 2 +- samples/cpp/npr_demo.cpp | 10 +- 9 files changed, 171 insertions(+), 249 deletions(-) mode change 100644 => 100755 modules/photo/test/test_npr.cpp diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst index 3a115e8390..48c5b24ba1 100644 --- a/modules/photo/doc/cloning.rst +++ b/modules/photo/doc/cloning.rst @@ -80,7 +80,7 @@ textureFlattening By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected region, giving its contents a flat aspect. Here Canny Edge Detector is used. -.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold, double high_threshold, int kernel_size) +.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold=30 , double high_threshold=45, int kernel_size=3) :param src: Input 8-bit 3-channel image. diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst index e547689876..48e2db2a7d 100644 --- a/modules/photo/doc/npr.rst +++ b/modules/photo/doc/npr.rst @@ -72,18 +72,3 @@ Stylization aims to produce digital imagery with a wide variety of effects not f :param sigma_s: Range between 0 to 200. :param sigma_r: Range between 0 to 1. - - -edgeEnhance ------------ -Able to suppress low-amplitude details and enhance edges. - -.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45) - - :param src: Input 8-bit 3-channel image. - - :param dst: Output 8-bit 1-channel image. - - :param sigma_s: Range between 0 to 200. - - :param sigma_r: Range between 0 to 1. diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 256366afad..949c1cfb62 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -93,213 +93,213 @@ namespace cv float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21); -enum { LDR_SIZE = 256 }; + enum { LDR_SIZE = 256 }; -class CV_EXPORTS_W Tonemap : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; + class CV_EXPORTS_W Tonemap : public Algorithm + { + public: + CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; - CV_WRAP virtual float getGamma() const = 0; - CV_WRAP virtual void setGamma(float gamma) = 0; -}; + CV_WRAP virtual float getGamma() const = 0; + CV_WRAP virtual void setGamma(float gamma) = 0; + }; -CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); + CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); -// "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 + // "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 -class CV_EXPORTS_W TonemapDrago : public Tonemap -{ -public: + class CV_EXPORTS_W TonemapDrago : public Tonemap + { + public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getBias() const = 0; - CV_WRAP virtual void setBias(float bias) = 0; -}; + CV_WRAP virtual float getBias() const = 0; + CV_WRAP virtual void setBias(float bias) = 0; + }; -CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); + CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); -// "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 + // "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 -class CV_EXPORTS_W TonemapDurand : public Tonemap -{ -public: + class CV_EXPORTS_W TonemapDurand : public Tonemap + { + public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getContrast() const = 0; - CV_WRAP virtual void setContrast(float contrast) = 0; + CV_WRAP virtual float getContrast() const = 0; + CV_WRAP virtual void setContrast(float contrast) = 0; - CV_WRAP virtual float getSigmaSpace() const = 0; - CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; + CV_WRAP virtual float getSigmaSpace() const = 0; + CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; - CV_WRAP virtual float getSigmaColor() const = 0; - CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; -}; + CV_WRAP virtual float getSigmaColor() const = 0; + CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; + }; -CV_EXPORTS_W Ptr -createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); + CV_EXPORTS_W Ptr + createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); -// "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 + // "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 -class CV_EXPORTS_W TonemapReinhard : public Tonemap -{ -public: - CV_WRAP virtual float getIntensity() const = 0; - CV_WRAP virtual void setIntensity(float intensity) = 0; + class CV_EXPORTS_W TonemapReinhard : public Tonemap + { + public: + CV_WRAP virtual float getIntensity() const = 0; + CV_WRAP virtual void setIntensity(float intensity) = 0; - CV_WRAP virtual float getLightAdaptation() const = 0; - CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; + CV_WRAP virtual float getLightAdaptation() const = 0; + CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; - CV_WRAP virtual float getColorAdaptation() const = 0; - CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; -}; + CV_WRAP virtual float getColorAdaptation() const = 0; + CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; + }; -CV_EXPORTS_W Ptr -createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); + CV_EXPORTS_W Ptr + createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); -// "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 + // "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 -class CV_EXPORTS_W TonemapMantiuk : public Tonemap -{ -public: - CV_WRAP virtual float getScale() const = 0; - CV_WRAP virtual void setScale(float scale) = 0; + class CV_EXPORTS_W TonemapMantiuk : public Tonemap + { + public: + CV_WRAP virtual float getScale() const = 0; + CV_WRAP virtual void setScale(float scale) = 0; - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; -}; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; + }; -CV_EXPORTS_W Ptr -createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); + CV_EXPORTS_W Ptr + createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); -class CV_EXPORTS_W AlignExposures : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; -}; + class CV_EXPORTS_W AlignExposures : public Algorithm + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; + }; -// "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 + // "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 -class CV_EXPORTS_W AlignMTB : public AlignExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; + class CV_EXPORTS_W AlignMTB : public AlignExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; - CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; - CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; - CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; + CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; + CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; + CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; - CV_WRAP virtual int getMaxBits() const = 0; - CV_WRAP virtual void setMaxBits(int max_bits) = 0; + CV_WRAP virtual int getMaxBits() const = 0; + CV_WRAP virtual void setMaxBits(int max_bits) = 0; - CV_WRAP virtual int getExcludeRange() const = 0; - CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; + CV_WRAP virtual int getExcludeRange() const = 0; + CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; - CV_WRAP virtual bool getCut() const = 0; - CV_WRAP virtual void setCut(bool value) = 0; -}; + CV_WRAP virtual bool getCut() const = 0; + CV_WRAP virtual void setCut(bool value) = 0; + }; -CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); + CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); -class CV_EXPORTS_W CalibrateCRF : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; -}; + class CV_EXPORTS_W CalibrateCRF : public Algorithm + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; + }; -// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 + // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 -class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF -{ -public: - CV_WRAP virtual float getLambda() const = 0; - CV_WRAP virtual void setLambda(float lambda) = 0; + class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF + { + public: + CV_WRAP virtual float getLambda() const = 0; + CV_WRAP virtual void setLambda(float lambda) = 0; - CV_WRAP virtual int getSamples() const = 0; - CV_WRAP virtual void setSamples(int samples) = 0; + CV_WRAP virtual int getSamples() const = 0; + CV_WRAP virtual void setSamples(int samples) = 0; - CV_WRAP virtual bool getRandom() const = 0; - CV_WRAP virtual void setRandom(bool random) = 0; -}; + CV_WRAP virtual bool getRandom() const = 0; + CV_WRAP virtual void setRandom(bool random) = 0; + }; -CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); + CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); -// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 + // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 -class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF -{ -public: - CV_WRAP virtual int getMaxIter() const = 0; - CV_WRAP virtual void setMaxIter(int max_iter) = 0; + class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF + { + public: + CV_WRAP virtual int getMaxIter() const = 0; + CV_WRAP virtual void setMaxIter(int max_iter) = 0; - CV_WRAP virtual float getThreshold() const = 0; - CV_WRAP virtual void setThreshold(float threshold) = 0; + CV_WRAP virtual float getThreshold() const = 0; + CV_WRAP virtual void setThreshold(float threshold) = 0; - CV_WRAP virtual Mat getRadiance() const = 0; -}; + CV_WRAP virtual Mat getRadiance() const = 0; + }; -CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); + CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); -class CV_EXPORTS_W MergeExposures : public Algorithm -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; -}; + class CV_EXPORTS_W MergeExposures : public Algorithm + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + }; -// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 + // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 -class CV_EXPORTS_W MergeDebevec : public MergeExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; -}; + class CV_EXPORTS_W MergeDebevec : public MergeExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; + }; -CV_EXPORTS_W Ptr createMergeDebevec(); + CV_EXPORTS_W Ptr createMergeDebevec(); -// "Exposure Fusion", Mertens et al., 2007 + // "Exposure Fusion", Mertens et al., 2007 -class CV_EXPORTS_W MergeMertens : public MergeExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; + class CV_EXPORTS_W MergeMertens : public MergeExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; - CV_WRAP virtual float getContrastWeight() const = 0; - CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; + CV_WRAP virtual float getContrastWeight() const = 0; + CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; - CV_WRAP virtual float getSaturationWeight() const = 0; - CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; + CV_WRAP virtual float getSaturationWeight() const = 0; + CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; - CV_WRAP virtual float getExposureWeight() const = 0; - CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; -}; + CV_WRAP virtual float getExposureWeight() const = 0; + CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; + }; -CV_EXPORTS_W Ptr -createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); + CV_EXPORTS_W Ptr + createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); -// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 + // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 -class CV_EXPORTS_W MergeRobertson : public MergeExposures -{ -public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; -}; + class CV_EXPORTS_W MergeRobertson : public MergeExposures + { + public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; + }; -CV_EXPORTS_W Ptr createMergeRobertson(); + CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); @@ -328,9 +328,6 @@ CV_EXPORTS_W Ptr createMergeRobertson(); CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); - CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); - } // cv #endif diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 6319d15513..54b9525af1 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -74,6 +74,13 @@ class Decolor void grayImContruct(vector &wei, Mat img, Mat &Gray); }; +int round_num(double a); + +int round_num(double a) +{ + return int(a + 0.5); +} + double Decolor::energyCalcu(vector &Cg, vector < vector > &polyGrad, vector &wei) { vector energy; @@ -228,7 +235,7 @@ void Decolor::weak_order(Mat img, vector &alf) if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); + resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); } Mat curIm = Mat(img.size(),CV_32FC1); @@ -304,7 +311,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad, if((h + w) > 800) { sizefactor = (double)800/(h+w); - resize(img,img,Size(round(h*sizefactor),round(w*sizefactor))); + resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor))); } h = img.size().height; diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp index a3b38d4ee1..3f0be9ba9f 100644 --- a/modules/photo/src/npr.cpp +++ b/modules/photo/src/npr.cpp @@ -151,7 +151,6 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig int h = img.size().height; int w = img.size().width; - int channel = img.channels(); Mat res = Mat(h,w,CV_32FC3); Mat magnitude = Mat(h,w,CV_32FC1); @@ -159,7 +158,7 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig Domain_Filter obj; obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - obj.find_magnitude(res,magnitude,2); + obj.find_magnitude(res,magnitude); Mat stylized = Mat(h,w,CV_32FC3); @@ -172,31 +171,3 @@ void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sig stylized.convertTo(dst,CV_8UC3,255); } - -void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r) -{ - Mat I = _src.getMat(); - _dst.create(I.size(), CV_8UC1); - Mat dst = _dst.getMat(); - - Mat img = Mat(I.size(),CV_32FC3); - I.convertTo(img,CV_32FC3,1.0/255.0); - - Mat orig = img.clone(); - - int h = img.size().height; - int w = img.size().width; - - Mat res = Mat(h,w,CV_32FC3); - Mat magnitude = Mat(h,w,CV_32FC1); - - Mat mag8 = Mat(h,w,CV_32FC1); - - Domain_Filter obj; - - obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER); - - obj.find_magnitude(res,magnitude,1); - - magnitude.convertTo(dst,CV_8UC1,255); -} diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 733d418d58..9658e25a6b 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -61,7 +61,7 @@ class Domain_Filter void getGradienty( const Mat &img, Mat &gy); void diffx(const Mat &img, Mat &temp); void diffy(const Mat &img, Mat &temp); - void find_magnitude(Mat &img, Mat &mag, int flags); + void find_magnitude(Mat &img, Mat &mag); void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius); void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h); void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius); @@ -131,7 +131,7 @@ void Domain_Filter::getGradienty( const Mat &img, Mat &gy) } } -void Domain_Filter::find_magnitude(Mat &img, Mat &mag, int flags) +void Domain_Filter::find_magnitude(Mat &img, Mat &mag) { int h = img.rows; int w = img.cols; @@ -148,28 +148,14 @@ void Domain_Filter::find_magnitude(Mat &img, Mat &mag, int flags) Mat magXB = Mat(h, w, CV_32FC1); Mat magYB = Mat(h, w, CV_32FC1); - if(flags == 1) - { - getGradientx(planes[0], magXR); - getGradienty(planes[0], magYR); - - getGradientx(planes[1], magXG); - getGradienty(planes[1], magYG); - - getGradientx(planes[2], magXR); - getGradienty(planes[2], magYR); - } - else if(flags == 2) - { - Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); - Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); + Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3); + Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3); - Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); - Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); + Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3); + Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3); - Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); - Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); - } + Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3); + Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3); Mat mag1 = Mat(h,w,CV_32FC1); Mat mag2 = Mat(h,w,CV_32FC1); diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp old mode 100644 new mode 100755 index 5d55d4c3b4..993f6c390f --- a/modules/photo/test/test_npr.cpp +++ b/modules/photo/test/test_npr.cpp @@ -128,19 +128,3 @@ TEST(Photo_NPR_Stylization, regression) imwrite(folder + "stylized.png", result); } - -TEST(Photo_NPR_EdgeEnhance, regression) -{ - string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/"; - string original_path = folder + "test1.png"; - - Mat source = imread(original_path, IMREAD_COLOR); - - ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path; - - Mat result; - edgeEnhance(source,result); - - imwrite(folder + "edge_enhanced.png", result); - -} diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index d9bcfb3eb6..7ff0100680 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -43,7 +43,7 @@ int main() cout << "6) Texture Flattening " << endl; cout << endl; cout << "Press number 1-6 to choose from above techniques: "; - int num; + int num = 1; cin >> num; cout << endl; diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp index e5e2528f13..30d30cba9f 100644 --- a/samples/cpp/npr_demo.cpp +++ b/samples/cpp/npr_demo.cpp @@ -11,7 +11,6 @@ * 2) Detail Enhancement * 3) Pencil sketch/Color Pencil Drawing * 4) Stylization -* 5) Edge Enhancement * */ @@ -57,10 +56,9 @@ int main(int argc, char* argv[]) cout << "2) Detail Enhancement" << endl; cout << "3) Pencil sketch/Color Pencil Drawing" << endl; cout << "4) Stylization" << endl; - cout << "5) Edge Enhancement" << endl; cout << endl; - cout << "Press number 1-5 to choose from above techniques: "; + cout << "Press number 1-4 to choose from above techniques: "; cin >> num; @@ -94,11 +92,5 @@ int main(int argc, char* argv[]) stylization(I,img); imshow("Stylization",img); } - else if(num == 5) - { - edgeEnhance(I,img); - imshow("Edge Enhance",img); - } - waitKey(0); } From 573e8184151e261c687db6fda5581fbabfdda907 Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 6 Nov 2013 20:29:01 +0530 Subject: [PATCH 24/27] New changes done and removed opencv_extra folder Removed opencv_extra folder inside opencv folder New changes done Removed test images --- modules/photo/src/contrast_preserve.hpp | 5 ++--- modules/photo/src/npr.hpp | 13 ++---------- modules/photo/src/seamless_cloning.hpp | 28 +++++++++---------------- 3 files changed, 14 insertions(+), 32 deletions(-) diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp index 54b9525af1..8a95170e32 100644 --- a/modules/photo/src/contrast_preserve.hpp +++ b/modules/photo/src/contrast_preserve.hpp @@ -427,7 +427,6 @@ void Decolor::grayImContruct(vector &wei, Mat img, Mat &Gray) maxval = Gray.at(i,j); } - for(int i=0;i(i,j) = (Gray.at(i,j) - minval)/(maxval - minval); + Gray -= minval; + Gray /= maxval - minval; } diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp index 9658e25a6b..744b2bdfbb 100644 --- a/modules/photo/src/npr.hpp +++ b/modules/photo/src/npr.hpp @@ -173,7 +173,6 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { int h = output.rows; int w = output.cols; - int channel = output.channels(); float a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h); @@ -190,11 +189,7 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { for(int j =1; j < w; j++) { - for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j-1)*channel+c) - temp.at(i,j*channel+c)) * V.at(i,j); - } + temp.at(i,j) = temp.at(i,j) + (temp.at(i,j-1) - temp.at(i,j)) * V.at(i,j); } } @@ -202,11 +197,7 @@ void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h) { for(int j =w-2; j >= 0; j--) { - for(int c = 0; c(i,j*channel+c) = temp.at(i,j*channel+c) + - (temp.at(i,(j+1)*channel+c) - temp.at(i,j*channel+c))*V.at(i,j+1); - } + temp.at(i,j) = temp.at(i,j) + (temp.at(i,j+1) - temp.at(i,j)) * V.at(i,j+1); } } diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 612d764d95..73d719c1ba 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -482,7 +482,6 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num) { int w = I.size().width; int h = I.size().height; - int channel = I.channels(); initialization(I,mask,wmask); @@ -496,25 +495,18 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num) { for(int i=0;i < h; i++) for(int j=0; j < w; j++) - for(int c=0;c(i,j) - sgy.at(i,j)) > abs(grx.at(i,j) - gry.at(i,j))) + { + srx32.at(i,j) = sgx.at(i,j) * smask.at(i,j); + sry32.at(i,j) = sgy.at(i,j) * smask.at(i,j); + } + else { - if(abs(sgx.at(i,j*channel+c) - sgy.at(i,j*channel+c)) > - abs(grx.at(i,j*channel+c) - gry.at(i,j*channel+c))) - { - - srx32.at(i,j*channel+c) = sgx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = sgy.at(i,j*channel+c) - * smask.at(i,j); - } - else - { - srx32.at(i,j*channel+c) = grx.at(i,j*channel+c) - * smask.at(i,j); - sry32.at(i,j*channel+c) = gry.at(i,j*channel+c) - * smask.at(i,j); - } + srx32.at(i,j) = grx.at(i,j) * smask.at(i,j); + sry32.at(i,j) = gry.at(i,j) * smask.at(i,j); } + } } else if(num == 3) { From 944f7bac42ac88dec6d92313720950fede6b373c Mon Sep 17 00:00:00 2001 From: Anna Kogan Date: Thu, 21 Nov 2013 15:45:53 +0400 Subject: [PATCH 25/27] After-merge corrections --- modules/photo/include/opencv2/photo.hpp | 403 ++++++++++++------------ 1 file changed, 203 insertions(+), 200 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index 949c1cfb62..b0e8e7d2be 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -52,281 +52,284 @@ namespace cv { - //! the inpainting algorithm - enum - { - INPAINT_NS = 0, // Navier-Stokes algorithm - INPAINT_TELEA = 1 // A. Telea algorithm - }; +//! the inpainting algorithm +enum +{ + INPAINT_NS = 0, // Navier-Stokes algorithm + INPAINT_TELEA = 1 // A. Telea algorithm +}; - enum - { - NORMAL_CLONE = 1, - MIXED_CLONE = 2, - MONOCHROME_TRANSFER = 3 - }; +enum +{ + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + MONOCHROME_TRANSFER = 3 +}; - enum - { - RECURS_FILTER = 1, - NORMCONV_FILTER = 2 - }; +enum +{ + RECURS_FILTER = 1, + NORMCONV_FILTER = 2 +}; - //! restores the damaged image areas using one of the available intpainting algorithms - CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, - OutputArray dst, double inpaintRadius, int flags ); +//! restores the damaged image areas using one of the available intpainting algorithms +CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask, + OutputArray dst, double inpaintRadius, int flags ); - CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, - int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3, + int templateWindowSize = 7, int searchWindowSize = 21); - CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); - CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, int templateWindowSize = 7, int searchWindowSize = 21); - CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, - int imgToDenoiseIndex, int temporalWindowSize, - float h = 3, float hColor = 3, - int templateWindowSize = 7, int searchWindowSize = 21); +CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst, + int imgToDenoiseIndex, int temporalWindowSize, + float h = 3, float hColor = 3, + int templateWindowSize = 7, int searchWindowSize = 21); - enum { LDR_SIZE = 256 }; +enum { LDR_SIZE = 256 }; - class CV_EXPORTS_W Tonemap : public Algorithm - { - public: - CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; +class CV_EXPORTS_W Tonemap : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArray src, OutputArray dst) = 0; - CV_WRAP virtual float getGamma() const = 0; - CV_WRAP virtual void setGamma(float gamma) = 0; - }; + CV_WRAP virtual float getGamma() const = 0; + CV_WRAP virtual void setGamma(float gamma) = 0; +}; - CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); +CV_EXPORTS_W Ptr createTonemap(float gamma = 1.0f); - // "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 +// "Adaptive Logarithmic Mapping For Displaying HighContrast Scenes", Drago et al., 2003 - class CV_EXPORTS_W TonemapDrago : public Tonemap - { - public: +class CV_EXPORTS_W TonemapDrago : public Tonemap +{ +public: - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getBias() const = 0; - CV_WRAP virtual void setBias(float bias) = 0; - }; + CV_WRAP virtual float getBias() const = 0; + CV_WRAP virtual void setBias(float bias) = 0; +}; - CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); +CV_EXPORTS_W Ptr createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f); - // "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 +// "Fast Bilateral Filtering for the Display of High-Dynamic-Range Images", Durand, Dorsey, 2002 - class CV_EXPORTS_W TonemapDurand : public Tonemap - { - public: +class CV_EXPORTS_W TonemapDurand : public Tonemap +{ +public: + + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; + CV_WRAP virtual float getContrast() const = 0; + CV_WRAP virtual void setContrast(float contrast) = 0; - CV_WRAP virtual float getContrast() const = 0; - CV_WRAP virtual void setContrast(float contrast) = 0; + CV_WRAP virtual float getSigmaSpace() const = 0; + CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; - CV_WRAP virtual float getSigmaSpace() const = 0; - CV_WRAP virtual void setSigmaSpace(float sigma_space) = 0; + CV_WRAP virtual float getSigmaColor() const = 0; + CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; +}; - CV_WRAP virtual float getSigmaColor() const = 0; - CV_WRAP virtual void setSigmaColor(float sigma_color) = 0; - }; +CV_EXPORTS_W Ptr +createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); - CV_EXPORTS_W Ptr - createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f); +// "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 - // "Dynamic Range Reduction Inspired by Photoreceptor Physiology", Reinhard, Devlin, 2005 +class CV_EXPORTS_W TonemapReinhard : public Tonemap +{ +public: + CV_WRAP virtual float getIntensity() const = 0; + CV_WRAP virtual void setIntensity(float intensity) = 0; - class CV_EXPORTS_W TonemapReinhard : public Tonemap - { - public: - CV_WRAP virtual float getIntensity() const = 0; - CV_WRAP virtual void setIntensity(float intensity) = 0; + CV_WRAP virtual float getLightAdaptation() const = 0; + CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; - CV_WRAP virtual float getLightAdaptation() const = 0; - CV_WRAP virtual void setLightAdaptation(float light_adapt) = 0; + CV_WRAP virtual float getColorAdaptation() const = 0; + CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; +}; - CV_WRAP virtual float getColorAdaptation() const = 0; - CV_WRAP virtual void setColorAdaptation(float color_adapt) = 0; - }; +CV_EXPORTS_W Ptr +createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); - CV_EXPORTS_W Ptr - createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f); +// "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 - // "Perceptual Framework for Contrast Processing of High Dynamic Range Images", Mantiuk et al., 2006 +class CV_EXPORTS_W TonemapMantiuk : public Tonemap +{ +public: + CV_WRAP virtual float getScale() const = 0; + CV_WRAP virtual void setScale(float scale) = 0; - class CV_EXPORTS_W TonemapMantiuk : public Tonemap - { - public: - CV_WRAP virtual float getScale() const = 0; - CV_WRAP virtual void setScale(float scale) = 0; + CV_WRAP virtual float getSaturation() const = 0; + CV_WRAP virtual void setSaturation(float saturation) = 0; +}; - CV_WRAP virtual float getSaturation() const = 0; - CV_WRAP virtual void setSaturation(float saturation) = 0; - }; +CV_EXPORTS_W Ptr +createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); - CV_EXPORTS_W Ptr - createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f); +class CV_EXPORTS_W AlignExposures : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; +}; - class CV_EXPORTS_W AlignExposures : public Algorithm - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; - }; +// "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 - // "Fast, Robust Image Registration for Compositing High Dynamic Range Photographs from Handheld Exposures", Ward, 2003 +class CV_EXPORTS_W AlignMTB : public AlignExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, + InputArray times, InputArray response) = 0; - class CV_EXPORTS_W AlignMTB : public AlignExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst, - InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, std::vector& dst) = 0; + CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; + CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; + CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; - CV_WRAP virtual Point calculateShift(InputArray img0, InputArray img1) = 0; - CV_WRAP virtual void shiftMat(InputArray src, OutputArray dst, const Point shift) = 0; - CV_WRAP virtual void computeBitmaps(InputArray img, OutputArray tb, OutputArray eb) = 0; + CV_WRAP virtual int getMaxBits() const = 0; + CV_WRAP virtual void setMaxBits(int max_bits) = 0; - CV_WRAP virtual int getMaxBits() const = 0; - CV_WRAP virtual void setMaxBits(int max_bits) = 0; + CV_WRAP virtual int getExcludeRange() const = 0; + CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; - CV_WRAP virtual int getExcludeRange() const = 0; - CV_WRAP virtual void setExcludeRange(int exclude_range) = 0; + CV_WRAP virtual bool getCut() const = 0; + CV_WRAP virtual void setCut(bool value) = 0; +}; - CV_WRAP virtual bool getCut() const = 0; - CV_WRAP virtual void setCut(bool value) = 0; - }; +CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); - CV_EXPORTS_W Ptr createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true); +class CV_EXPORTS_W CalibrateCRF : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; - class CV_EXPORTS_W CalibrateCRF : public Algorithm - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; - }; +// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 - // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 +class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF +{ +public: + CV_WRAP virtual float getLambda() const = 0; + CV_WRAP virtual void setLambda(float lambda) = 0; - class CV_EXPORTS_W CalibrateDebevec : public CalibrateCRF - { - public: - CV_WRAP virtual float getLambda() const = 0; - CV_WRAP virtual void setLambda(float lambda) = 0; + CV_WRAP virtual int getSamples() const = 0; + CV_WRAP virtual void setSamples(int samples) = 0; - CV_WRAP virtual int getSamples() const = 0; - CV_WRAP virtual void setSamples(int samples) = 0; + CV_WRAP virtual bool getRandom() const = 0; + CV_WRAP virtual void setRandom(bool random) = 0; +}; - CV_WRAP virtual bool getRandom() const = 0; - CV_WRAP virtual void setRandom(bool random) = 0; - }; +CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); - CV_EXPORTS_W Ptr createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false); +// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 - // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 +class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF +{ +public: + CV_WRAP virtual int getMaxIter() const = 0; + CV_WRAP virtual void setMaxIter(int max_iter) = 0; - class CV_EXPORTS_W CalibrateRobertson : public CalibrateCRF - { - public: - CV_WRAP virtual int getMaxIter() const = 0; - CV_WRAP virtual void setMaxIter(int max_iter) = 0; + CV_WRAP virtual float getThreshold() const = 0; + CV_WRAP virtual void setThreshold(float threshold) = 0; - CV_WRAP virtual float getThreshold() const = 0; - CV_WRAP virtual void setThreshold(float threshold) = 0; + CV_WRAP virtual Mat getRadiance() const = 0; +}; - CV_WRAP virtual Mat getRadiance() const = 0; - }; +CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); - CV_EXPORTS_W Ptr createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f); +class CV_EXPORTS_W MergeExposures : public Algorithm +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; +}; - class CV_EXPORTS_W MergeExposures : public Algorithm - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - }; +// "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 - // "Recovering High Dynamic Range Radiance Maps from Photographs", Debevec, Malik, 1997 +class CV_EXPORTS_W MergeDebevec : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; - class CV_EXPORTS_W MergeDebevec : public MergeExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; - }; +CV_EXPORTS_W Ptr createMergeDebevec(); - CV_EXPORTS_W Ptr createMergeDebevec(); +// "Exposure Fusion", Mertens et al., 2007 - // "Exposure Fusion", Mertens et al., 2007 +class CV_EXPORTS_W MergeMertens : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; - class CV_EXPORTS_W MergeMertens : public MergeExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst) = 0; + CV_WRAP virtual float getContrastWeight() const = 0; + CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; - CV_WRAP virtual float getContrastWeight() const = 0; - CV_WRAP virtual void setContrastWeight(float contrast_weiht) = 0; + CV_WRAP virtual float getSaturationWeight() const = 0; + CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; - CV_WRAP virtual float getSaturationWeight() const = 0; - CV_WRAP virtual void setSaturationWeight(float saturation_weight) = 0; + CV_WRAP virtual float getExposureWeight() const = 0; + CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; +}; - CV_WRAP virtual float getExposureWeight() const = 0; - CV_WRAP virtual void setExposureWeight(float exposure_weight) = 0; - }; +CV_EXPORTS_W Ptr +createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); - CV_EXPORTS_W Ptr - createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f); +// "Dynamic range improvement through multiple exposures", Robertson et al., 1999 - // "Dynamic range improvement through multiple exposures", Robertson et al., 1999 +class CV_EXPORTS_W MergeRobertson : public MergeExposures +{ +public: + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, + InputArray times, InputArray response) = 0; + CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; +}; - class CV_EXPORTS_W MergeRobertson : public MergeExposures - { - public: - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, - InputArray times, InputArray response) = 0; - CV_WRAP virtual void process(InputArrayOfArrays src, OutputArray dst, InputArray times) = 0; - }; +CV_EXPORTS_W Ptr createMergeRobertson(); - CV_EXPORTS_W Ptr createMergeRobertson(); +CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); - CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost); +CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, + OutputArray blend, int flags); - CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, - OutputArray blend, int flags); +CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, + float green_mul = 1.0, float blue_mul = 1.0); - CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, - float green_mul = 1.0, float blue_mul = 1.0); +CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, + float alpha = 0.2, float beta = 0.4); - CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, - float alpha = 0.2, float beta = 0.4); +CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, + double low_threshold, double high_threshold, + int kernel_size); - CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold = 30, double high_threshold = 45, - int kernel_size = 3); +CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, + float sigma_s = 60, float sigma_r = 0.4); - CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, - float sigma_s = 60, float sigma_r = 0.4); +CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, + float sigma_r = 0.15); - CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, - float sigma_r = 0.15); +CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, + float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); - CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, - float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02); +CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); - CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); +CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, + float sigma_r = 0.45); } // cv From c48ad880f39ec5f36e7aa2c6bec8ff3fea375cc0 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 22 Nov 2013 23:37:41 +0530 Subject: [PATCH 26/27] Errors resolved --- modules/photo/include/opencv2/photo.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp index b0e8e7d2be..7ca933c3f6 100644 --- a/modules/photo/include/opencv2/photo.hpp +++ b/modules/photo/include/opencv2/photo.hpp @@ -313,8 +313,8 @@ CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArra float alpha = 0.2, float beta = 0.4); CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst, - double low_threshold, double high_threshold, - int kernel_size); + double low_threshold = 30, double high_threshold = 45, + int kernel_size = 3); CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4); @@ -328,9 +328,6 @@ CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45); -CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, - float sigma_r = 0.45); - } // cv #endif From 778edff9e1bf2606504f8bc804f34f26470b48b7 Mon Sep 17 00:00:00 2001 From: siddharth Date: Wed, 4 Dec 2013 19:12:43 +0530 Subject: [PATCH 27/27] Added comment in demo file --- samples/cpp/cloning_demo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/samples/cpp/cloning_demo.cpp b/samples/cpp/cloning_demo.cpp index 7ff0100680..65a57f1497 100644 --- a/samples/cpp/cloning_demo.cpp +++ b/samples/cpp/cloning_demo.cpp @@ -16,6 +16,9 @@ * The program takes as input a source and a destination image (for 1-3 methods) * and ouputs the cloned image. +* +* Download test images from opencv_extra folder @github. +* */ #include "opencv2/photo.hpp"