opencv3.0中的无缝克隆图像——seamless_cloning(Poisson Image Editing)

opencv3.0 photo 模块加入了seamless_cloning类。该类对应的论文是“Poisson Image Editing”

主要可以实现一下功能:

seamless clone:

opencv3.0中的无缝克隆图像——seamless_cloning(Poisson Image Editing)_第1张图片

纹理传输:

opencv3.0中的无缝克隆图像——seamless_cloning(Poisson Image Editing)_第2张图片


去除光噪:

opencv3.0中的无缝克隆图像——seamless_cloning(Poisson Image Editing)_第3张图片

等等。


本文主要以normal_clone为例, 从代码层面解释整个流程:

1.  在normal_clone 中需要准备三张图片,分别是source, mask, destination。 如最上面那张图,source就是熊,孩子那些要黏贴的图片,mask是这些前景的mask。 destination是背景,这里是水池。

2. 计算source和destination的x,y方向上的梯度

3. 计算lapx, lapy即对梯度再取梯度。得到lap

4. 取destination中非mask位置和source中mask位置lap,两者拼接得到最终lap

5. 用这个lap和原始图片,解决possion equation, 得到最终结果。(这部分不是很懂

用到了Discrete sine transform, 

参考:http://www.mathworks.com/help/pde/ug/dst.html
   http://www.mathworks.com/help/pde/ug/fast-solution-of-poissons-equation.html


注释代码如下:(做了少量修改,与opencv不完全相同)

[cpp]  view plain  copy
  1. #ifndef SEAMLESSCLONE_H_H  
  2. #define SEAMLESSCLONE_H_H   
  3.   
  4.   
  5. //#include "precomp.hpp"  
  6. //#include "opencv2/photo.hpp"  
  7. #include "opencv2/imgproc.hpp"  
  8. #include "opencv2/core/core.hpp"  
  9. #include   
  10. #include   
  11. #include   
  12. #include "math.h"  
  13.   
  14. using namespace std;  
  15. using namespace cv;  
  16.   
  17. namespace customCV {  
  18.   
  19.     class Cloning  
  20.     {  
  21.   
  22.     public:  
  23.   
  24.         //output: 每个通道的合成结果数组  
  25.         //rbgx_channel, rgby_channel是gxx, gyy 分通道结果  
  26.         vector  rgb_channel, rgbx_channel, rgby_channel, output;  
  27.   
  28.         //smask是source图片的mask, smask1是smask取反的结果  
  29.         //grx, gry 是dst图片的梯度。 grx32, gry32是smask1区域的梯度  
  30.         //sgx, sgy 是source图片的梯度。 srx32, sry32是smask区域的梯度  
  31.         Mat grx, gry, sgx, sgy, srx32, sry32, grx32, gry32, smask, smask1;  
  32.         void init_var(Mat &I, Mat &wmask);  
  33.         void initialization(Mat &I, Mat &mask, Mat &wmask);  
  34.         void scalar_product(Mat mat, float r, float g, float b);  
  35.         void array_product(Mat mat1, Mat mat2, Mat mat3);  
  36.         void poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy);  
  37.         void evaluate(Mat &I, Mat &wmask, Mat &cloned);  
  38.         void getGradientx(const Mat &img, Mat &gx);  
  39.         void getGradienty(const Mat &img, Mat &gy);  
  40.         void lapx(const Mat &img, Mat &gxx);  
  41.         void lapy(const Mat &img, Mat &gyy);  
  42.         void dst(double *mod_diff, double *sineTransform, int h, int w);  
  43.         void idst(double *mod_diff, double *sineTransform, int h, int w);  
  44.         void transpose(double *mat, double *mat_t, int h, int w);  
  45.         void solve(const Mat &img, double *mod_diff, Mat &result);  
  46.         void poisson_solver(const Mat &img, Mat &gxx, Mat &gyy, Mat &result);  
  47.         void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num);  
  48.         void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul, float green_mul, float blue_mul);  
  49.         void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta);  
  50.         void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &cloned);  
  51.     };  
  52.   
  53.   
  54.   
  55.   
  56.     void seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags);  
  57.     void colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b);  
  58.     void illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b);  
  59.     void textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst, double low_threshold, double high_threshold, int kernel_size);  
  60.   
  61. }  
  62.   
  63. #endif  

[cpp]  view plain  copy
  1. //#include "precomp.hpp"  
  2. //#include "opencv2/photo.hpp"  
  3. #include   
  4. #include   
  5.   
  6. #include "seamless_cloning.hpp"  
  7.   
  8. using namespace std;  
  9. using namespace cv;  
  10.   
  11. namespace customCV {  
  12.   
  13.     void Cloning::getGradientx(const Mat &img, Mat &gx)  
  14.     {  
  15.         Mat kernel = Mat::zeros(1, 3, CV_8S);  
  16.         kernel.at<char>(0, 2) = 1;  
  17.         kernel.at<char>(0, 1) = -1;  
  18.         filter2D(img, gx, CV_32F, kernel);  
  19.     }  
  20.   
  21.     void Cloning::getGradienty(const Mat &img, Mat &gy)  
  22.     {  
  23.         Mat kernel = Mat::zeros(3, 1, CV_8S);  
  24.         kernel.at<char>(2, 0) = 1;  
  25.         kernel.at<char>(1, 0) = -1;  
  26.         filter2D(img, gy, CV_32F, kernel);  
  27.     }  
  28.   
  29.     //img是原始图像水平方向上的梯度。本函数是对梯度再求梯度  
  30.     void Cloning::lapx(const Mat &img, Mat &gxx)  
  31.     {  
  32.         Mat kernel = Mat::zeros(1, 3, CV_8S);  
  33.         kernel.at<char>(0, 0) = -1;  
  34.         kernel.at<char>(0, 1) = 1;  
  35.         filter2D(img, gxx, CV_32F, kernel);  
  36.     }  
  37.   
  38.     void Cloning::lapy(const Mat &img, Mat &gyy)  
  39.     {  
  40.         Mat kernel = Mat::zeros(3, 1, CV_8S);  
  41.         kernel.at<char>(0, 0) = -1;  
  42.         kernel.at<char>(1, 0) = 1;  
  43.         filter2D(img, gyy, CV_32F, kernel);  
  44.     }  
  45.   
  46.     //离散正弦变换  
  47.     //参考:http://www.mathworks.com/help/pde/ug/dst.html  
  48.     //参考:http://www.mathworks.com/help/pde/ug/fast-solution-of-poissons-equation.html  
  49.     void Cloning::dst(double *mod_diff, double *sineTransform, int h, int w)  
  50.     {  
  51.   
  52.         unsigned long int idx;  
  53.   
  54.         Mat temp = Mat(2 * h + 2, 1, CV_32F);  
  55.         Mat res = Mat(h, 1, CV_32F);  
  56.   
  57.         Mat planes[] = { Mat_<float>(temp), Mat::zeros(temp.size(), CV_32F) };  
  58.   
  59.         Mat result;  
  60.         int p = 0;  
  61.         for (int i = 0; i < w; i++)  
  62.         {  
  63.             temp.at<float>(0, 0) = 0.0;  
  64.   
  65.             for (int j = 0, r = 1; j < h; j++, r++)  
  66.             {  
  67.                 idx = j*w + i;  
  68.                 temp.at<float>(r, 0) = (float)mod_diff[idx];  
  69.             }  
  70.   
  71.             temp.at<float>(h + 1, 0) = 0.0;  
  72.   
  73.             for (int j = h - 1, r = h + 2; j >= 0; j--, r++)  
  74.             {  
  75.                 idx = j*w + i;  
  76.                 temp.at<float>(r, 0) = (float)(-1.0 * mod_diff[idx]);  
  77.             }  
  78.   
  79.             merge(planes, 2, result);  
  80.   
  81.             dft(result, result, 0, 0);  
  82.   
  83.             Mat planes1[] = { Mat::zeros(result.size(), CV_32F), Mat::zeros(result.size(), CV_32F) };  
  84.   
  85.             split(result, planes1);  
  86.   
  87.             std::complex<double> two_i = std::sqrt(std::complex<double>(-1));  
  88.   
  89.             double factor = -2 * imag(two_i);  
  90.   
  91.             for (int c = 1, z = 0; c < h + 1; c++, z++)  
  92.             {  
  93.                 res.at<float>(z, 0) = (float)(planes1[1].at<float>(c, 0) / factor);  
  94.             }  
  95.   
  96.             for (int q = 0, z = 0; q < h; q++, z++)  
  97.             {  
  98.                 idx = q*w + p;  
  99.                 sineTransform[idx] = res.at<float>(z, 0);  
  100.             }  
  101.             p++;  
  102.         }  
  103.     }  
  104.   
  105.     void Cloning::idst(double *mod_diff, double *sineTransform, int h, int w)  
  106.     {  
  107.         int nn = h + 1;  
  108.         unsigned long int idx;  
  109.         dst(mod_diff, sineTransform, h, w);  
  110.         for (int i = 0; i < h; i++)  
  111.         for (int j = 0; j < w; j++)  
  112.         {  
  113.             idx = i*w + j;  
  114.             sineTransform[idx] = (double)(2 * sineTransform[idx]) / nn;  
  115.         }  
  116.   
  117.     }  
  118.   
  119.     void Cloning::transpose(double *mat, double *mat_t, int h, int w)  
  120.     {  
  121.   
  122.         Mat tmp = Mat(h, w, CV_32FC1);  
  123.         unsigned long int idx;  
  124.         for (int i = 0; i < h; i++)  
  125.         {  
  126.             for (int j = 0; j < w; j++)  
  127.             {  
  128.   
  129.                 idx = i*(w)+j;  
  130.                 tmp.at<float>(i, j) = (float)mat[idx];  
  131.             }  
  132.         }  
  133.         Mat tmp_t = tmp.t();  
  134.   
  135.         for (int i = 0; i < tmp_t.size().height; i++)  
  136.         for (int j = 0; j < tmp_t.size().width; j++)  
  137.         {  
  138.             idx = i*tmp_t.size().width + j;  
  139.             mat_t[idx] = tmp_t.at<float>(i, j);  
  140.         }  
  141.     }  
  142.   
  143.     void Cloning::solve(const Mat &img, double *mod_diff, Mat &result)  
  144.     {  
  145.         int w = img.size().width;  
  146.         int h = img.size().height;  
  147.   
  148.         unsigned long int idx, idx1;  
  149.   
  150.         double *sineTransform = new double[(h - 2)*(w - 2)];  
  151.         double *sineTransform_t = new double[(h - 2)*(w - 2)];  
  152.         double *denom = new double[(h - 2)*(w - 2)];  
  153.         double *invsineTransform = new double[(h - 2)*(w - 2)];  
  154.         double *invsineTransform_t = new double[(h - 2)*(w - 2)];  
  155.         double *img_d = new double[(h)*(w)];  
  156.         //结果存在img_d  
  157.   
  158.           
  159.         dst(mod_diff, sineTransform, h - 2, w - 2);  
  160.         transpose(sineTransform, sineTransform_t, h - 2, w - 2);  
  161.   
  162.   
  163.         dst(sineTransform_t, sineTransform, w - 2, h - 2);  
  164.   
  165.         transpose(sineTransform, sineTransform_t, w - 2, h - 2);  
  166.   
  167.         int cy = 1;  
  168.   
  169.         for (int i = 0; i < w - 2; i++, cy++)  
  170.         {  
  171.             for (int j = 0, cx = 1; j < h - 2; j++, cx++)  
  172.             {  
  173.                 idx = j*(w - 2) + i;  
  174.                 denom[idx] = (float)2 * cos(CV_PI*cy / ((double)(w - 1))) - 2 + 2 * cos(CV_PI*cx / ((double)(h - 1))) - 2;  
  175.   
  176.             }  
  177.         }  
  178.   
  179.         for (idx = 0; idx < (unsigned)(w - 2)*(h - 2); idx++)  
  180.         {  
  181.             sineTransform_t[idx] = sineTransform_t[idx] / denom[idx];  
  182.         }  
  183.   
  184.         idst(sineTransform_t, invsineTransform, h - 2, w - 2);  
  185.   
  186.         transpose(invsineTransform, invsineTransform_t, h - 2, w - 2);  
  187.   
  188.         idst(invsineTransform_t, invsineTransform, w - 2, h - 2);  
  189.   
  190.         transpose(invsineTransform, invsineTransform_t, w - 2, h - 2);  
  191.   
  192.         for (int i = 0; i < h; i++)  
  193.         {  
  194.             for (int j = 0; j < w; j++)  
  195.             {  
  196.                 idx = i*w + j;  
  197.                 img_d[idx] = (double)img.at(i, j);  
  198.             }  
  199.         }  
  200.         for (int i = 1; i < h - 1; i++)  
  201.         {  
  202.             for (int j = 1; j < w - 1; j++)  
  203.             {  
  204.                 idx = i*w + j;  
  205.                 img_d[idx] = 0.0;  
  206.             }  
  207.         }  
  208.         for (int i = 1, id1 = 0; i < h - 1; i++, id1++)  
  209.         {  
  210.             for (int j = 1, id2 = 0; j < w - 1; j++, id2++)  
  211.             {  
  212.                 idx = i*w + j;  
  213.                 idx1 = id1*(w - 2) + id2;  
  214.                 img_d[idx] = invsineTransform_t[idx1];  
  215.             }  
  216.         }  
  217.   
  218.   
  219.         for (int i = 0; i < h; i++)  
  220.         {  
  221.             for (int j = 0; j < w; j++)  
  222.             {  
  223.                 idx = i*w + j;  
  224.                 if (img_d[idx] < 0.0) {  
  225.                     result.at(i, j) = 0;  
  226.                 }  
  227.                 else if (img_d[idx] > 255.0)  
  228.                     result.at(i, j) = 255;  
  229.                 else {  
  230.                     result.at(i, j) = (uchar)img_d[idx];  
  231.                 }  
  232.             }  
  233.         }  
  234.   
  235.         delete[] sineTransform;  
  236.         delete[] sineTransform_t;  
  237.         delete[] denom;  
  238.         delete[] invsineTransform;  
  239.         delete[] invsineTransform_t;  
  240.         delete[] img_d;  
  241.     }  
  242.   
  243.     //由img和lap计算合成结果, 注意实际上lap有大量负数  
  244.     void Cloning::poisson_solver(const Mat &img, Mat &gxx, Mat &gyy, Mat &result)  
  245.     {  
  246.   
  247.         int w = img.size().width;  
  248.         int h = img.size().height;  
  249.   
  250.         unsigned long int idx;  
  251.   
  252.         Mat lap = Mat(img.size(), CV_32FC1);  
  253.   
  254.         lap = gxx + gyy;  
  255.   
  256.         Mat bound = img.clone();  
  257.           
  258.         //rectangle 外围保持原样,rect内部变为scalar  
  259.         rectangle(bound, Point(1, 1), Point(img.cols - 2, img.rows - 2), Scalar::all(0), -1);  
  260.         //rectangle(bound, Point(20, 20), Point(img.cols - 50, img.rows - 50), Scalar::all(0), -1);  
  261.   
  262.   
  263.         double *boundary_point = new double[h*w];  
  264.   
  265.         Mat bound_map = cv::Mat(img.size(), CV_8UC1, cv::Scalar(0));  
  266.   
  267.         for (int i = 1; i < h - 1; i++)  
  268.         for (int j = 1; j < w - 1; j++)  
  269.         {  
  270.             idx = i*w + j;  
  271.             boundary_point[idx] = -4 * (int)bound.at(i, j) + (int)bound.at(i, (j + 1)) + (int)bound.at(i, (j - 1))  
  272.                 + (int)bound.at(i - 1, j) + (int)bound.at(i + 1, j);  
  273.             bound_map.at(i, j) = boundary_point[idx];  
  274.         }  
  275.   
  276.   
  277.   
  278.         Mat diff = Mat(h, w, CV_32FC1);  
  279.         for (int i = 0; i < h; i++)  
  280.         {  
  281.             for (int j = 0; j < w; j++)  
  282.             {  
  283.                 idx = i*w + j;  
  284.                 diff.at<float>(i, j) = (float)(lap.at<float>(i, j) - boundary_point[idx]);  
  285.             }  
  286.         }  
  287.   
  288.         //diff和lap几乎没什么区别  
  289.   
  290.         double *mod_diff = new double[(h - 2)*(w - 2)];  
  291.         for (int i = 0; i < h - 2; i++)  
  292.         {  
  293.             for (int j = 0; j < w - 2; j++)  
  294.             {  
  295.                 idx = i*(w - 2) + j;  
  296.                 mod_diff[idx] = diff.at<float>(i + 1, j + 1);  
  297.   
  298.             }  
  299.         }  
  300.         ///////////////////////////////////////////////////// Find DST  /////////////////////////////////////////////////////  
  301.         solve(img, mod_diff, result);  
  302.   
  303.         delete[] mod_diff;  
  304.         delete[] boundary_point;  
  305.     }  
  306.   
  307.     void Cloning::init_var(Mat &I, Mat &wmask)  
  308.     {  
  309.         grx = Mat(I.size(), CV_32FC3);  
  310.         gry = Mat(I.size(), CV_32FC3);  
  311.         sgx = Mat(I.size(), CV_32FC3);  
  312.         sgy = Mat(I.size(), CV_32FC3);  
  313.   
  314.         split(I, rgb_channel);  
  315.   
  316.   
  317.         smask = Mat(wmask.size(), CV_32FC1);  
  318.         srx32 = Mat(I.size(), CV_32FC3);  
  319.         sry32 = Mat(I.size(), CV_32FC3);  
  320.         smask1 = Mat(wmask.size(), CV_32FC1);  
  321.         grx32 = Mat(I.size(), CV_32FC3);  
  322.         gry32 = Mat(I.size(), CV_32FC3);  
  323.     }  
  324.   
  325.     void Cloning::initialization(Mat &I, Mat &mask, Mat &wmask)  
  326.     {  
  327.         //初始化各个mat  
  328.         init_var(I, wmask);  
  329.   
  330.         //grx, gry 分别表示dest的x,y方向的梯度  
  331.         getGradientx(I, grx);  
  332.         getGradienty(I, gry);  
  333.   
  334.         //sgx, sgy 分别表示在mask区域内的source图片在x,y方向的梯度  
  335.         getGradientx(mask, sgx);  
  336.         getGradienty(mask, sgy);  
  337.   
  338.         Mat Kernel(Size(3, 3), CV_8UC1);  
  339.         Kernel.setTo(Scalar(1));  
  340.         //腐蚀  
  341.         erode(wmask, wmask, Kernel, Point(-1, -1), 3);  
  342.   
  343.         wmask.convertTo(smask, CV_32FC1, 1.0 / 255.0);  
  344.         I.convertTo(srx32, CV_32FC3, 1.0 / 255.0);  
  345.         I.convertTo(sry32, CV_32FC3, 1.0 / 255.0);  
  346.     }  
  347.   
  348.     void Cloning::scalar_product(Mat mat, float r, float g, float b)  
  349.     {  
  350.         vector  channels;  
  351.         split(mat, channels);  
  352.         multiply(channels[2], r, channels[2]);  
  353.         multiply(channels[1], g, channels[1]);  
  354.         multiply(channels[0], b, channels[0]);  
  355.         merge(channels, mat);  
  356.     }  
  357.   
  358.     //mat1 = mat3.mul(mat2(:))  mat3为单通道,一般为mask  
  359.     void Cloning::array_product(Mat mat1, Mat mat2, Mat mat3)  
  360.     {  
  361.         vector  channels_temp1;  
  362.         vector  channels_temp2;  
  363.         split(mat1, channels_temp1);  
  364.         split(mat2, channels_temp2);  
  365.         multiply(channels_temp2[2], mat3, channels_temp1[2]);  
  366.         multiply(channels_temp2[1], mat3, channels_temp1[1]);  
  367.         multiply(channels_temp2[0], mat3, channels_temp1[0]);  
  368.         merge(channels_temp1, mat1);  
  369.     }  
  370.   
  371.     void Cloning::poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy)  
  372.     {  
  373.         //fx, fy是两者组合的梯度  
  374.         Mat fx = Mat(I.size(), CV_32FC3);  
  375.         Mat fy = Mat(I.size(), CV_32FC3);  
  376.   
  377.         fx = gx + sx;  
  378.         fy = gy + sy;  
  379.   
  380.   
  381.         Mat gxx = Mat(I.size(), CV_32FC3);  
  382.         Mat gyy = Mat(I.size(), CV_32FC3);  
  383.   
  384.         //gxx, gyy 是在x,y方向的laplacian算子  
  385.         lapx(fx, gxx);  
  386.         lapy(fy, gyy);  
  387.   
  388.   
  389.         split(gxx, rgbx_channel);  
  390.         split(gyy, rgby_channel);  
  391.   
  392.         split(I, output);  
  393.   
  394.   
  395.         poisson_solver(rgb_channel[2], rgbx_channel[2], rgby_channel[2], output[2]);  
  396.         poisson_solver(rgb_channel[1], rgbx_channel[1], rgby_channel[1], output[1]);  
  397.         poisson_solver(rgb_channel[0], rgbx_channel[0], rgby_channel[0], output[0]);  
  398.     }  
  399.   
  400.     void Cloning::evaluate(Mat &I, Mat &wmask, Mat &cloned)  
  401.     {  
  402.         //mask取反  
  403.         bitwise_not(wmask, wmask);  
  404.   
  405.         wmask.convertTo(smask1, CV_32FC1, 1.0 / 255.0);  
  406.         I.convertTo(grx32, CV_32FC3, 1.0 / 255.0);  
  407.         I.convertTo(gry32, CV_32FC3, 1.0 / 255.0);  
  408.   
  409.         array_product(grx32, grx, smask1);  
  410.         array_product(gry32, gry, smask1);  
  411.   
  412.         poisson(I, grx32, gry32, srx32, sry32);  
  413.   
  414.         merge(output, cloned);  
  415.     }  
  416.   
  417.     void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num)  
  418.     {  
  419.         int w = I.size().width;  
  420.         int h = I.size().height;  
  421.         int channel = I.channels();  
  422.   
  423.         //初始化各个存储参数的mat,并计算原图于目标图的x,y方向梯度,对mask腐蚀  
  424.         initialization(I, mask, wmask);  
  425.   
  426.         if (num == 1) //NORMAL_CLONE  
  427.         {  
  428.             //srx32, sry32是sgx,sgy的mask区域  
  429.             array_product(srx32, sgx, smask);  
  430.             array_product(sry32, sgy, smask);  
  431.         }  
  432.         else if (num == 2) //MIXED_CLONE  
  433.         {  
  434.   
  435.             for (int i = 0; i < h; i++)  
  436.             {  
  437.                 for (int j = 0; j < w; j++)  
  438.                 {  
  439.                     for (int c = 0; c
  440.                     {  
  441.                         if (abs(sgx.at<float>(i, j*channel + c) - sgy.at<float>(i, j*channel + c)) >  
  442.                             abs(grx.at<float>(i, j*channel + c) - gry.at<float>(i, j*channel + c)))  
  443.                         {  
  444.   
  445.                             srx32.at<float>(i, j*channel + c) = sgx.at<float>(i, j*channel + c)  
  446.                                 * smask.at<float>(i, j);  
  447.                             sry32.at<float>(i, j*channel + c) = sgy.at<float>(i, j*channel + c)  
  448.                                 * smask.at<float>(i, j);  
  449.                         }  
  450.                         else  
  451.                         {  
  452.                             srx32.at<float>(i, j*channel + c) = grx.at<float>(i, j*channel + c)  
  453.                                 * smask.at<float>(i, j);  
  454.                             sry32.at<float>(i, j*channel + c) = gry.at<float>(i, j*channel + c)  
  455.                                 * smask.at<float>(i, j);  
  456.                         }  
  457.                     }  
  458.                 }  
  459.             }  
  460.   
  461.         }  
  462.         else if (num == 3) //FEATURE_EXCHANGE  
  463.         {  
  464.             Mat gray = Mat(mask.size(), CV_8UC1);  
  465.             Mat gray8 = Mat(mask.size(), CV_8UC3);  
  466.             cvtColor(mask, gray, COLOR_BGR2GRAY);  
  467.             vector  temp;  
  468.             split(I, temp);  
  469.             gray.copyTo(temp[2]);  
  470.             gray.copyTo(temp[1]);  
  471.             gray.copyTo(temp[0]);  
  472.   
  473.             merge(temp, gray8);  
  474.   
  475.             getGradientx(gray8, sgx);  
  476.             getGradienty(gray8, sgy);  
  477.   
  478.             array_product(srx32, sgx, smask);  
  479.             array_product(sry32, sgy, smask);  
  480.   
  481.         }  
  482.   
  483.         evaluate(I, wmask, cloned);  
  484.     }  
  485.   
  486.     void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul = 1.0,  
  487.         float green_mul = 1.0, float blue_mul = 1.0)  
  488.     {  
  489.         initialization(I, mask, wmask);  
  490.   
  491.         array_product(srx32, sgx, smask);  
  492.         array_product(sry32, sgy, smask);  
  493.         scalar_product(srx32, red_mul, green_mul, blue_mul);  
  494.         scalar_product(sry32, red_mul, green_mul, blue_mul);  
  495.   
  496.         evaluate(I, wmask, cloned);  
  497.     }  
  498.   
  499.     void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta)  
  500.     {  
  501.         initialization(I, mask, wmask);  
  502.   
  503.         array_product(srx32, sgx, smask);  
  504.         array_product(sry32, sgy, smask);  
  505.   
  506.         Mat mag = Mat(I.size(), CV_32FC3);  
  507.         magnitude(srx32, sry32, mag);  
  508.   
  509.         //opencv3.0 alpha中有bug,需要加入一下代码才不能得到正确结果。已经提交bug  
  510.         for (int i = 0; i < mag.cols; i++)  
  511.         {  
  512.             for (int j = 0; j < mag.rows; j++)  
  513.             {  
  514.                 if (mag.at(j, i)[0] == 0)  
  515.                     mag.at(j, i)[0] = 1e-8;  
  516.   
  517.                 if (mag.at(j, i)[1] == 0)  
  518.                     mag.at(j, i)[1] = 1e-8;  
  519.   
  520.                 if (mag.at(j, i)[2] == 0)  
  521.                     mag.at(j, i)[2] = 1e-8;  
  522.             }  
  523.         }  
  524.   
  525.         Mat multX, multY, multx_temp, multy_temp;  
  526.   
  527.         multiply(srx32, pow(alpha, beta), multX);  
  528.         pow(mag, -1 * beta, multx_temp);  
  529.         multiply(multX, multx_temp, srx32);  
  530.   
  531.         multiply(sry32, pow(alpha, beta), multY);  
  532.         pow(mag, -1 * beta, multy_temp);  
  533.         multiply(multY, multy_temp, sry32);  
  534.   
  535.         Mat zeroMask = (srx32 != 0);  
  536.   
  537.         srx32.copyTo(srx32, zeroMask);  
  538.         sry32.copyTo(sry32, zeroMask);  
  539.   
  540.         evaluate(I, wmask, cloned);  
  541.     }  
  542.   
  543.     void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold,  
  544.         double high_threshold, int kernel_size, Mat &cloned)  
  545.     {  
  546.         initialization(I, mask, wmask);  
  547.   
  548.         Mat out = Mat(mask.size(), CV_8UC1);  
  549.         Canny(mask, out, low_threshold, high_threshold, kernel_size);  
  550.   
  551.         Mat zeros(sgx.size(), CV_32FC3);  
  552.         zeros.setTo(0);  
  553.         Mat zerosMask = (out != 255);  
  554.         zeros.copyTo(sgx, zerosMask);  
  555.         zeros.copyTo(sgy, zerosMask);  
  556.   
  557.         array_product(srx32, sgx, smask);  
  558.         array_product(sry32, sgy, smask);  
  559.   
  560.         evaluate(I, wmask, cloned);  
  561.     }  
  562.   
  563.   
  564.   
  565.     void seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)  
  566.     {  
  567.         Mat src = _src.getMat();  
  568.         Mat dest = _dst.getMat();  
  569.         Mat mask = _mask.getMat();  
  570.         _blend.create(dest.size(), CV_8UC3);  
  571.         Mat blend = _blend.getMat();  
  572.   
  573.         int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;  
  574.         int h = mask.size().height;  
  575.         int w = mask.size().width;  
  576.   
  577.         Mat gray = Mat(mask.size(), CV_8UC1);  
  578.         Mat dst_mask = Mat::zeros(dest.size(), CV_8UC1);  
  579.         Mat cs_mask = Mat::zeros(src.size(), CV_8UC3);  
  580.         Mat cd_mask = Mat::zeros(dest.size(), CV_8UC3);  
  581.   
  582.         if (mask.channels() == 3)  
  583.             cvtColor(mask, gray, COLOR_BGR2GRAY);  
  584.         else  
  585.             gray = mask;  
  586.   
  587.         for (int i = 0; i < h; i++)  
  588.         {  
  589.             for (int j = 0; j < w; j++)  
  590.             {  
  591.                 if (gray.at(i, j) == 255)  
  592.                 {  
  593.                     minx = std::min(minx, i);  
  594.                     maxx = std::max(maxx, i);  
  595.                     miny = std::min(miny, j);  
  596.                     maxy = std::max(maxy, j);  
  597.                 }  
  598.             }  
  599.         }  
  600.   
  601.         int lenx = maxx - minx;  
  602.         int leny = maxy - miny;  
  603.   
  604.         int minxd = p.y - lenx / 2;  
  605.         int maxxd = p.y + lenx / 2;  
  606.         int minyd = p.x - leny / 2;  
  607.         int maxyd = p.x + leny / 2;  
  608.   
  609.         CV_Assert(minxd >= 0 && minyd >= 0 && maxxd <= dest.rows && maxyd <= dest.cols);  
  610.   
  611.         Rect roi_d(minyd, minxd, leny, lenx);  
  612.         Rect roi_s(miny, minx, leny, lenx);  
  613.   
  614.         Mat destinationROI = dst_mask(roi_d);  
  615.         Mat sourceROI = cs_mask(roi_s);  
  616.   
  617.         gray(roi_s).copyTo(destinationROI);  
  618.         src(roi_s).copyTo(sourceROI, gray(roi_s));  
  619.   
  620.         destinationROI = cd_mask(roi_d);  
  621.         cs_mask(roi_s).copyTo(destinationROI);  
  622.   
  623.         Cloning obj;  
  624.         obj.normal_clone(dest, cd_mask, dst_mask, blend, flags);  
  625.   
  626.     }  
  627.   
  628.     void colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b)  
  629.     {  
  630.         Mat src = _src.getMat();  
  631.         Mat mask = _mask.getMat();  
  632.         _dst.create(src.size(), src.type());  
  633.         Mat blend = _dst.getMat();  
  634.   
  635.         float red = r;  
  636.         float green = g;  
  637.         float blue = b;  
  638.   
  639.         Mat gray = Mat::zeros(mask.size(), CV_8UC1);  
  640.   
  641.         if (mask.channels() == 3)  
  642.             cvtColor(mask, gray, COLOR_BGR2GRAY);  
  643.         else  
  644.             gray = mask;  
  645.   
  646.         Mat cs_mask = Mat::zeros(src.size(), CV_8UC3);  
  647.   
  648.         src.copyTo(cs_mask, gray);  
  649.   
  650.         Cloning obj;  
  651.         obj.local_color_change(src, cs_mask, gray, blend, red, green, blue);  
  652.     }  
  653.   
  654.     void illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b)  
  655.     {  
  656.   
  657.         Mat src = _src.getMat();  
  658.         Mat mask = _mask.getMat();  
  659.         _dst.create(src.size(), src.type());  
  660.         Mat blend = _dst.getMat();  
  661.         float alpha = a;  
  662.         float beta = b;  
  663.   
  664.         Mat gray = Mat::zeros(mask.size(), CV_8UC1);  
  665.   
  666.         if (mask.channels() == 3)  
  667.             cvtColor(mask, gray, COLOR_BGR2GRAY);  
  668.         else  
  669.             gray = mask;  
  670.   
  671.         Mat cs_mask = Mat::zeros(src.size(), CV_8UC3);  
  672.   
  673.         src.copyTo(cs_mask, gray);  
  674.   
  675.         Cloning obj;  
  676.         obj.illum_change(src, cs_mask, gray, blend, alpha, beta);  
  677.     }  
  678.   
  679.     void textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,  
  680.         double low_threshold, double high_threshold, int kernel_size)  
  681.     {  
  682.   
  683.         Mat src = _src.getMat();  
  684.         Mat mask = _mask.getMat();  
  685.         _dst.create(src.size(), src.type());  
  686.         Mat blend = _dst.getMat();  
  687.   
  688.         Mat gray = Mat::zeros(mask.size(), CV_8UC1);  
  689.   
  690.         if (mask.channels() == 3)  
  691.             cvtColor(mask, gray, COLOR_BGR2GRAY);  
  692.         else  
  693.             gray = mask;  
  694.   
  695.         Mat cs_mask = Mat::zeros(src.size(), CV_8UC3);  
  696.   
  697.         src.copyTo(cs_mask, gray);  
  698.   
  699.         Cloning obj;  
  700.         obj.texture_flatten(src, cs_mask, gray, low_threshold, high_threshold, kernel_size, blend);  
  701.     }  
  702.   
  703. }  

你可能感兴趣的:(视觉/图像处理opencv)