Commit c6901646 authored by Adrien BAK's avatar Adrien BAK

replace implementation of dst

parent 89e78605
...@@ -65,10 +65,9 @@ namespace cv ...@@ -65,10 +65,9 @@ namespace cv
void scalar_product(cv::Mat mat, float r, float g, float b); void scalar_product(cv::Mat mat, float r, float g, float b);
void poisson(const cv::Mat &destination); void poisson(const cv::Mat &destination);
void evaluate(const cv::Mat &I, const cv::Mat &wmask, const cv::Mat &cloned); void evaluate(const cv::Mat &I, const cv::Mat &wmask, const cv::Mat &cloned);
void dst(const std::vector<float>& mod_diff, std::vector<float>& sineTransform,int h,int w); void dst(const Mat& src, Mat& dest, bool invert = false);
void idst(const std::vector<float>& mod_diff, std::vector<float>& sineTransform,int h,int w); void idst(const Mat& src, Mat& dest);
void transpose(const std::vector<float>& mat, std::vector<float>& mat_t,int h,int w); void solve(const cv::Mat &img, std::vector<float>& mod_diff, cv::Mat &result);
void solve(const cv::Mat &img, const std::vector<float>& mod_diff, cv::Mat &result);
void poisson_solver(const cv::Mat &img, cv::Mat &gxx , cv::Mat &gyy, 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; void array_product(const cv::Mat& lhs, const cv::Mat& rhs, cv::Mat& result) const;
...@@ -83,6 +82,8 @@ namespace cv ...@@ -83,6 +82,8 @@ namespace cv
cv::Mat destinationGradientX, destinationGradientY; cv::Mat destinationGradientX, destinationGradientY;
cv::Mat patchGradientX, patchGradientY; cv::Mat patchGradientX, patchGradientY;
cv::Mat binaryMaskFloat, binaryMaskFloatInverted; cv::Mat binaryMaskFloat, binaryMaskFloatInverted;
std::vector<float> filter_X, filter_Y;
}; };
} }
#endif #endif
\ No newline at end of file
...@@ -81,141 +81,76 @@ void Cloning::computeLaplacianY( const Mat &img, Mat &laplacianY) ...@@ -81,141 +81,76 @@ void Cloning::computeLaplacianY( const Mat &img, Mat &laplacianY)
filter2D(img, laplacianY, CV_32F, kernel); filter2D(img, laplacianY, CV_32F, kernel);
} }
void Cloning::dst(const std::vector<float>& mod_diff, std::vector<float>& 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;
Mat temp = Mat(2*h+2,1,CV_32F); src.copyTo(temp(Rect(1,0, src.cols, src.rows)));
Mat res = Mat(h,1,CV_32F);
Mat planes[] = {Mat_<float>(temp), Mat::zeros(temp.size(), CV_32F)};
Mat result;
int p=0;
const float factor = 0.5;
for(int i=0;i<w;i++) for(int j = 0 ; j < src.rows ; ++j)
{ {
temp.at<float>(0,0) = 0.0; for(int i = 0 ; i < src.cols ; ++i)
for(int j=0,r=1;j<h;j++,r++)
{ {
idx = j*w+i; temp.ptr<float>(j)[src.cols + 2 + i] = - src.ptr<float>(j)[src.cols - 1 - i];
temp.at<float>(r,0) = (float) mod_diff[idx];
} }
}
temp.at<float>(h+1,0)=0.0; Mat planes[] = {temp, Mat::zeros(temp.size(), CV_32F)};
Mat complex;
for(int j=h-1, r=h+2;j>=0;j--,r++)
{
idx = j*w+i;
temp.at<float>(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<h+1;c++,z++) merge(planes, 2, complex);
{ dft(complex, complex, flag);
res.at<float>(z,0) = (float) (planes1[1].at<float>(c,0) * factor); split(complex, planes);
}
temp = Mat::zeros(src.cols, 2 * src.rows + 2, CV_32F);
for(int q=0,z=0;q<h;q++,z++) for(int j = 0 ; j < src.cols ; ++j)
{
for(int i = 0 ; i < src.rows ; ++i)
{ {
idx = q*w+p; float val = planes[1].ptr<float>(i)[j + 1];
sineTransform[idx] = res.at<float>(z,0); temp.ptr<float>(j)[i + 1] = val;
temp.ptr<float>(j)[temp.cols - 1 - i] = - val;
} }
p++;
} }
}
Mat planes2[] = {temp, Mat::zeros(temp.size(), CV_32F)};
void Cloning::idst(const std::vector<float>& mod_diff, std::vector<float>& sineTransform,int h,int w) merge(planes2, 2, complex);
{ dft(complex, complex, flag);
int nn = h+1; split(complex, planes2);
unsigned long int idx;
dst(mod_diff,sineTransform,h,w);
for(int i= 0;i<h;i++)
for(int j=0;j<w;j++)
{
idx = i*w + j;
sineTransform[idx] = (float) (2*sineTransform[idx])/nn;
}
temp = planes2[1].t();
dest = Mat::zeros(src.size(), CV_32F);
temp(Rect( 0, 1, src.cols, src.rows)).copyTo(dest);
} }
void Cloning::transpose(const std::vector<float>& mat, std::vector<float>& mat_t,int h,int w) void Cloning::idst(const Mat& src, Mat& dest)
{ {
dst(src, dest, true);
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<float>(i,j) = (float) mat[idx];
}
}
Mat tmp_t = tmp.t();
for(int i = 0;i < tmp_t.size().height; i++)
for(int j=0;j<tmp_t.size().width;j++)
{
idx = i*tmp_t.size().width + j;
mat_t[idx] = tmp_t.at<float>(i,j);
}
} }
void Cloning::solve(const Mat &img, const std::vector<float>& mod_diff, Mat &result) void Cloning::solve(const Mat &img, std::vector<float>& mod_diff, Mat &result)
{ {
const int w = img.size().width; const int w = img.size().width;
const int h = img.size().height; const int h = img.size().height;
std::vector<float> sineTransform((h-2)*(w-2), 0.);
std::vector<float> sineTranformTranspose((h-2)*(w-2), 0.);
std::vector<float> denom((h-2)*(w-2), 0.);
std::vector<float> invsineTransform((h-2)*(w-2), 0.);
std::vector<float> 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);
Mat ModDiff(h-2, w-2, CV_32F, &mod_diff[0]);
for(int j = 0,cx = 1; j < h-2; j++,cx++) 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; res.ptr<float>(j)[i] /= (filter_X[i] + filter_Y[j] - 4);
denom[idx] = 2*cos(CV_PI*cy/( w-1)) + 2*cos(CV_PI*cx/(h-1)) - 4;
} }
} }
for(int idx = 0 ; idx < (w-2)*(h-2) ;idx++) idst(res, ModDiff);
{
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);
//first col //first col
for(int i = 0 ; i < w ; ++i) for(int i = 0 ; i < w ; ++i)
...@@ -228,10 +163,9 @@ void Cloning::solve(const Mat &img, const std::vector<float>& mod_diff, Mat &res ...@@ -228,10 +163,9 @@ void Cloning::solve(const Mat &img, const std::vector<float>& mod_diff, Mat &res
for(int i = 1 ; i < w-1 ; ++i) 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 //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. //most notable, saturate_cast rounds before truncating, here it's the opposite.
float value = invsineTransform_t[idx]; float value = ModDiff.ptr<float>(j-1)[i-1];
if(value < 0.) if(value < 0.)
result.ptr<unsigned char>(j)[i] = 0; result.ptr<unsigned char>(j)[i] = 0;
else if (value > 255.0) else if (value > 255.0)
...@@ -267,6 +201,7 @@ void Cloning::poisson_solver(const Mat &img, Mat &laplacianX , Mat &laplacianY, ...@@ -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); rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1);
std::vector<float> boundary_point(h*w, 0.); std::vector<float> boundary_point(h*w, 0.);
for(int i =1;i<h-1;i++) for(int i =1;i<h-1;i++)
...@@ -311,6 +246,17 @@ void Cloning::init_var(const Mat &destination, const Mat &binaryMask) ...@@ -311,6 +246,17 @@ void Cloning::init_var(const Mat &destination, const Mat &binaryMask)
binaryMaskFloat = Mat(binaryMask.size(),CV_32FC1); binaryMaskFloat = Mat(binaryMask.size(),CV_32FC1);
binaryMaskFloatInverted = Mat(binaryMask.size(),CV_32FC1); binaryMaskFloatInverted = Mat(binaryMask.size(),CV_32FC1);
//init of the filters used in the dft
const int w = destination.size().width;
filter_X.resize(w - 2);
for(int i = 0 ; i < w-2 ; ++i)
filter_X[i] = 2.0f * std::cos(CV_PI * (i + 1) / (w - 1));
const int h = destination.size().height;
filter_Y.resize(h - 2);
for(int j = 0 ; j < h - 2 ; ++j)
filter_Y[j] = 2.0f * std::cos(CV_PI * (j + 1) / (h - 1));
} }
void Cloning::compute_derivatives(const Mat& destination, const Mat &patch, const Mat &binaryMask) void Cloning::compute_derivatives(const Mat& destination, const Mat &patch, const Mat &binaryMask)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment