From c69016467dcb44d92cee283115f5b1e71cbf9179 Mon Sep 17 00:00:00 2001 From: Adrien BAK Date: Tue, 7 Oct 2014 17:11:59 +0900 Subject: [PATCH] replace implementation of dst --- modules/photo/src/seamless_cloning.hpp | 9 +- modules/photo/src/seamless_cloning_impl.cpp | 176 +++++++------------- 2 files changed, 66 insertions(+), 119 deletions(-) diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp index 3b589ec7f..8fcb93b08 100644 --- a/modules/photo/src/seamless_cloning.hpp +++ b/modules/photo/src/seamless_cloning.hpp @@ -65,10 +65,9 @@ namespace cv void scalar_product(cv::Mat mat, float r, float g, float b); void poisson(const cv::Mat &destination); void evaluate(const cv::Mat &I, const cv::Mat &wmask, const cv::Mat &cloned); - void dst(const std::vector& mod_diff, std::vector& sineTransform,int h,int w); - void idst(const std::vector& mod_diff, std::vector& sineTransform,int h,int w); - void transpose(const std::vector& mat, std::vector& mat_t,int h,int w); - void solve(const cv::Mat &img, const std::vector& mod_diff, cv::Mat &result); + void dst(const Mat& src, Mat& dest, bool invert = false); + void idst(const Mat& src, Mat& dest); + void solve(const cv::Mat &img, std::vector& mod_diff, cv::Mat &result); void poisson_solver(const cv::Mat &img, cv::Mat &gxx , cv::Mat &gyy, cv::Mat &result); void array_product(const cv::Mat& lhs, const cv::Mat& rhs, cv::Mat& result) const; @@ -83,6 +82,8 @@ namespace cv cv::Mat destinationGradientX, destinationGradientY; cv::Mat patchGradientX, patchGradientY; cv::Mat binaryMaskFloat, binaryMaskFloatInverted; + + std::vector filter_X, filter_Y; }; } #endif \ No newline at end of file diff --git a/modules/photo/src/seamless_cloning_impl.cpp b/modules/photo/src/seamless_cloning_impl.cpp index 42fa6800e..5eb60899a 100644 --- a/modules/photo/src/seamless_cloning_impl.cpp +++ b/modules/photo/src/seamless_cloning_impl.cpp @@ -81,141 +81,76 @@ void Cloning::computeLaplacianY( const Mat &img, Mat &laplacianY) filter2D(img, laplacianY, CV_32F, kernel); } -void Cloning::dst(const std::vector& mod_diff, std::vector& sineTransform,int h,int w) +void Cloning::dst(const Mat& src, Mat& dest, bool invert) { + Mat temp = Mat::zeros(src.rows, 2 * src.cols + 2, CV_32F); - unsigned long int idx; + int flag = invert ? DFT_ROWS + DFT_SCALE + DFT_INVERSE: DFT_ROWS; + + src.copyTo(temp(Rect(1,0, src.cols, src.rows))); - 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 result; - int p=0; - - const float factor = 0.5; - - for(int i=0;i(0,0) = 0.0; - - for(int j=0,r=1;j(r,0) = (float) mod_diff[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) = (float) (-1.0 * mod_diff[idx]); - } - - merge(planes, 2, result); - - dft(result,result,0,0); - - Mat planes1[] = {Mat::zeros(result.size(), CV_32F), Mat::zeros(result.size(), CV_32F)}; - - split(result, planes1); - - for(int c=1,z=0;c(z,0) = (float) (planes1[1].at(c,0) * factor); - } - - for(int q=0,z=0;q(z,0); - } - p++; - } -} - -void Cloning::idst(const std::vector& mod_diff, std::vector& sineTransform,int h,int w) -{ - int nn = h+1; - unsigned long int idx; - dst(mod_diff,sineTransform,h,w); - for(int i= 0;i& mat, std::vector& mat_t,int h,int w) -{ - - Mat tmp = Mat(h,w,CV_32FC1); - unsigned long int idx; - for(int i = 0 ; i < h;i++) - { - for(int j = 0 ; j < w; j++) - { - - idx = i*(w) + j; - tmp.at(i,j) = (float) mat[idx]; + temp.ptr(j)[src.cols + 2 + i] = - src.ptr(j)[src.cols - 1 - i]; } } - Mat tmp_t = tmp.t(); - for(int i = 0;i < tmp_t.size().height; i++) - for(int j=0;j(i,j); + float val = planes[1].ptr(i)[j + 1]; + temp.ptr(j)[i + 1] = val; + temp.ptr(j)[temp.cols - 1 - i] = - val; } + } + + Mat planes2[] = {temp, Mat::zeros(temp.size(), CV_32F)}; + + merge(planes2, 2, complex); + dft(complex, complex, flag); + split(complex, planes2); + + temp = planes2[1].t(); + dest = Mat::zeros(src.size(), CV_32F); + temp(Rect( 0, 1, src.cols, src.rows)).copyTo(dest); } -void Cloning::solve(const Mat &img, const std::vector& mod_diff, Mat &result) +void Cloning::idst(const Mat& src, Mat& dest) +{ + dst(src, dest, true); +} + +void Cloning::solve(const Mat &img, std::vector& mod_diff, Mat &result) { const int w = img.size().width; const int h = img.size().height; - std::vector sineTransform((h-2)*(w-2), 0.); - std::vector sineTranformTranspose((h-2)*(w-2), 0.); - std::vector denom((h-2)*(w-2), 0.); - std::vector invsineTransform((h-2)*(w-2), 0.); - std::vector invsineTransform_t((h-2)*(w-2), 0.); - dst(mod_diff,sineTransform,h-2,w-2); - - transpose(sineTransform,sineTranformTranspose,h-2,w-2); - - dst(sineTranformTranspose,sineTransform,w-2,h-2); - - transpose(sineTransform,sineTranformTranspose,w-2,h-2); - - - for(int j = 0,cx = 1; j < h-2; j++,cx++) + Mat ModDiff(h-2, w-2, CV_32F, &mod_diff[0]); + Mat res; + dst(ModDiff, res); + + for(int j = 0 ; j < h-2; j++) { - for(int i = 0, cy=1 ; i < w-2;i++,cy++) + for(int i = 0 ; i < w-2; i++) { - int idx = j*(w-2) + i; - denom[idx] = 2*cos(CV_PI*cy/( w-1)) + 2*cos(CV_PI*cx/(h-1)) - 4; - + res.ptr(j)[i] /= (filter_X[i] + filter_Y[j] - 4); } } - for(int idx = 0 ; idx < (w-2)*(h-2) ;idx++) - { - sineTranformTranspose[idx] = sineTranformTranspose[idx]/denom[idx]; - } - - idst(sineTranformTranspose,invsineTransform,h-2,w-2); - - transpose(invsineTransform,invsineTransform_t,h-2,w-2); - - idst(invsineTransform_t,invsineTransform,w-2,h-2); - - transpose(invsineTransform,invsineTransform_t,w-2,h-2); + idst(res, ModDiff); //first col for(int i = 0 ; i < w ; ++i) @@ -228,10 +163,9 @@ void Cloning::solve(const Mat &img, const std::vector& mod_diff, Mat &res for(int i = 1 ; i < w-1 ; ++i) { - int idx = (j-1)* (w-2) + (i-1); //saturate cast is not used here, because it behaves differently from the previous implementation //most notable, saturate_cast rounds before truncating, here it's the opposite. - float value = invsineTransform_t[idx]; + float value = ModDiff.ptr(j-1)[i-1]; if(value < 0.) result.ptr(j)[i] = 0; else if (value > 255.0) @@ -267,6 +201,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &laplacianX , Mat &laplacianY, rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1); + std::vector boundary_point(h*w, 0.); for(int i =1;i