// Calculate b // using convolution. Mat PoissonBlending::getB1(Mat &src, Mat &dst, Mat &roiMask,vector<Point>&Points,Point loc, Rect ROI) { Mat lapMat; int mh = roiMask.rows; int mw = roiMask.cols; filter2D(src, lapMat, -1, getLaplacian()); Mat B = Mat::zeros(Points.size(), 1, CV_32FC1); for (int i = 0; i < Points.size(); i++) { Point pt = Points[i]; double tmp = 0.0; tmp = lapMat.ATF(ROI.y + pt.y, ROI.x + pt.x); if (pt.y>0 && roiMask.ATU(pt.y - 1, pt.x) != 255) tmp -= dst.ATF(pt.y + loc.y - 1, pt.x + loc.x); if (pt.y+1 <mh && roiMask.ATU(pt.y + 1, pt.x) != 255) tmp -= dst.ATF(pt.y + loc.y + 1, pt.x + loc.x); if (pt.x + 1<mw && roiMask.ATU(pt.y, pt.x + 1) != 255) tmp -= dst.ATF(pt.y + loc.y, pt.x + loc.x + 1); if (pt.x>0 && roiMask.ATU(pt.y , pt.x-1) != 255) tmp -= dst.ATF(pt.y + loc.y, pt.x + loc.x - 1); B.ATF(i, 0) = tmp; } return B; }
// Calculate b // using Gradients Mixing. Mat PoissonBlending::getB3(Mat &src, Mat &dst, Mat &roiMask, vector<Point>&Points, Point loc, Rect ROI) { Mat gradMat = getGradient(src) + getGradient(dst); int mh = roiMask.rows; int mw = roiMask.cols; Mat B = Mat::zeros(Points.size(), 1, CV_32FC1); for (int i = 0; i < Points.size(); i++) { Point pt = Points[i]; double tmp = 0.0; tmp = gradMat.ATF(ROI.y + pt.y, ROI.x + pt.x); if (pt.y>0 && roiMask.ATU(pt.y - 1, pt.x) != 255) tmp -= dst.ATF(pt.y + loc.y - 1, pt.x + loc.x); if (pt.y + 1<mh && roiMask.ATU(pt.y + 1, pt.x) != 255) tmp -= dst.ATF(pt.y + loc.y + 1, pt.x + loc.x); if (pt.x + 1<mw && roiMask.ATU(pt.y, pt.x + 1) != 255) tmp -= dst.ATF(pt.y + loc.y, pt.x + loc.x + 1); if (pt.x>0 && roiMask.ATU(pt.y, pt.x - 1) != 255) tmp -= dst.ATF(pt.y + loc.y, pt.x + loc.x - 1); B.ATF(i, 0) = tmp; } return B; }
// img1: 3-channel image, we wanna move something in it into img2. // img2: 3-channel image, dst image. // ROI: the position and size of the block we want to move in img1. // posX, posY: where we want to move the block to in img2 void PoissonBlending::poisson_blending(Mat &src, Mat &dst, Mat &result, Mat &roiMask, Rect roi, Point loc) { cout << "Poisson Blender" << endl; src.convertTo(src, CV_32FC3); src /= 255; dst.convertTo(dst, CV_32FC3); dst /= 255; vector<Point> Points; #pragma omp parallel for for (int i = 0; i < roi.height; i++) { #pragma omp parallel for for (int j = 0; j < roi.width; j++) { int z=roiMask.ATU(i, j); if (roiMask.ATU(i, j) == 255) { #pragma omp critical(ppb) { Points.push_back(Point(j, i)); } } } } cout << "Total Points: " << Points.size()<< endl; cout << "Calculating Matrix A" << endl; Mat A = getA(roiMask, Points); // we must do the poisson blending to each channel. vector<Mat> src_rgb; split(src, src_rgb); vector<Mat> dst_rgb; split(dst, dst_rgb); vector<Mat> res_v; res_v.resize(3); cout << "Calculating B" << endl; // process 3 channels #pragma omp parallel for schedule(dynamic, 1) for (int i = 0; i < 3; i++) { #pragma omp critical(cout) cout << " " << i + 1 << "/3 channel processing..." << endl; Mat res, b; b = getB2(src_rgb[i], dst_rgb[i], roiMask, Points, loc, roi); //b = getB1(src_rgb[i], dst_rgb[i], roiMask, Points, loc, roi); #pragma omp critical(cout) res = getResult(A, b); #pragma omp critical(res_v) res_v[i]=res; #pragma omp critical(cout) cout << " "<< i + 1 << "/3 channel finished!!!" << endl; } Mat res_m; // merge the 3 gray images into a 3-channel image cout << "Merging result" << endl; merge(res_v, res_m); dst.copyTo(result); #pragma omp parallel for for (int i = 0; i < res_m.rows; i++) { Point p = Points[i]+Point(roi.x,roi.y); result.at<Vec3f>(p) = res_m.at<Vec3f>(i, 0); } }