From 0802c06571e89b7ae66a7e008d5eb1f4115c7dd6 Mon Sep 17 00:00:00 2001 From: siddharth Date: Fri, 12 Jul 2013 09:18:37 +0530 Subject: [PATCH] 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 e656b93..fd05b4c 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 0000000..abb9636 --- /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 0000000..acff705 --- /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); + } +} -- 2.7.4