克拉玛依住房和建设局网站,做推广哪个平台好,淘宝客网站开发一个,广州市数商云泊松融合是一种很重要的图像融合算法#xff0c;该算法选自论文#xff08;[Poisson Image Editing]2003年发表#xff09;#xff0c;关于算法中的很多基础概念可以参考如下博客#xff1a; https://blog.csdn.net/hjimce/article/details/45716603 https://blog.csdn.…泊松融合是一种很重要的图像融合算法该算法选自论文[Poisson Image Editing]2003年发表关于算法中的很多基础概念可以参考如下博客 https://blog.csdn.net/hjimce/article/details/45716603 https://blog.csdn.net/zxpddfg/article/details/75825965 http://eric-yuan.me/poisson-blending/ 还有另一个博客也是自己实现了一遍泊松融合算法网址如下 https://blog.csdn.net/dengheCSDN/article/details/77862567 关于泊松融合的算法在opencv3.0以上的版本已经有接口。下面的代码没有用opencv内置的接口是自己完整的实现了一遍该算法对于我们理解整个算法有很大的帮助。
源图片src.jpg 背景图片dst.jpg 掩膜图片mask.jpg 首先理解什么是图像融合图像融合是把src.jpgmask.jpg重叠下可以显示的部分ROI融合到dst.jpg中融合到dst.jpg中时我们需要为ROI设计在dst.jpg的坐标我们设置为dst.jpg的图像中心。也就是说src.jpgmask.jpg重叠的部分我们要融合到dst.jgp的中心位置。
算法计算步骤:
得到ROI图片把ROI图片重新命名为src.jpg计算src.jpg的每一个像素点的梯度值同时也计算dst.jpg的每一个像素点的梯度值对两者进行比较把梯度更高的值存储在矩阵b中这样可以让融合后的图像边缘更平滑。 关于图像梯度的解释https://blog.csdn.net/qq_19764963/article/details/44342389构建稀疏矩阵A矩阵A每行有5个非零元素五个元素呈现这个样子(..1..1..-4..1..1..)其中每个元素分别对应A的该行对应的像素点的四个相邻像素和本身像素。类似求卷积。最后solve()函数中利用高斯赛德尔方法计算得出融合后的图像x把x中每个像素点分别替换到dst.jpg的相应位置中即可得到融合后的结果。**
我们要理解图像中矩阵相乘的概念 稀疏矩阵A的行数和列数都等于 (ROI.rows*ROI.cols)也就是说如果要融合的区域是100*100像素的矩阵A的行为10000列也为10000 整个公式为 A*x b其中x为最终融合的图像b为我们对每个像素点计算出的散度也就是卷积的结果b也是一个矩阵b的行数为10000列数为1我们也要把ROI区域的图像变为10000*1的矩阵也就是x如果ROI区域是彩色的我们就要分别计算R,G,B对应的三个矩阵如果是灰色的我们就只需要计算一个矩阵最后把x贴到dst.jpg中就完成融合。 该公式大体上为我们对每一个像素计算出该位置的散度b然后手动的构建稀疏矩阵A最后反向计算出图像xx即为最终结果。
/*
代码选自http://blog.csdn.net/zxpddfg/article/details/75825965
CSDN博客 泊松图像融合算法C实现
opencv版本2.4.9代码最重要的是
1.建立稀疏矩阵类class SparseMat
2.计算融合图像时用到的稀疏矩阵SparseMat A、融合后的图像散度矩阵 b
3.依据A,b得到融合后的图像x
所以最重要的两个函数为
void getEquation()
void solve()算法流程
1.计算稀疏矩阵A
2.计算散度矩阵b
3.初始化融合图像x初始化只是简单的把源图像复制到目的图像的ROI区域
4.依据A,b得到最终的x
*/
#include opencv2/core/core.hpp
#include opencv2/imgproc/imgproc.hpp
#include opencv2/highgui/highgui.hpp
#include cmath
#include cstdio
#include cstdlib
#include cstring
#include vector
#include iostream
using namespace std;struct IndexedValue
{IndexedValue() : index(-1), value(0) {}IndexedValue(int index_, double value_) : index(index_), value(value_) {}int index;double value;
};struct SparseMat
{SparseMat() : rows(0), maxCols(0) {}SparseMat(int rows_, int cols_) :rows(0), maxCols(0){create(rows_, cols_);}void create(int rows_, int cols_){CV_Assert(rows_ 0 cols_ 0);rows rows_;maxCols cols_;buf.resize(rows * maxCols);data buf[0];memset(data, -1, rows * maxCols * sizeof(IndexedValue));count.resize(rows);memset(count[0], 0, rows * sizeof(int));}void release(){rows 0;maxCols 0;buf.clear();count.clear();data 0;}/*获取第row行的行指针*/const IndexedValue* rowPtr(int row) const{CV_Assert(row 0 row rows);return data row * maxCols;}IndexedValue* rowPtr(int row){CV_Assert(row 0 row rows);return data row * maxCols;}/*可以抽象的理解为在(row,col)位置插入value值但是存储该值的时候是从前往后依次存储的并且存储了该值的索引*/void insert(int row, int col, double value){CV_Assert(row 0 row rows);int currCount count[row];CV_Assert(currCount maxCols);IndexedValue* rowData rowPtr(row);int i 0;if ((currCount 0) (col rowData[0].index)){for (i 1; i currCount; i){if ((col rowData[i - 1].index) (col rowData[i].index))break;}}if (i currCount){for (int j currCount; j i; j--)rowData[j 1] rowData[j];}rowData[i] IndexedValue(col, value);count[row];}/*可以得到对角线元素i,i处于第几个位置用vectorintpos记录pos[i]0,1,2三个数字之一*/void calcDiagonalElementsPositions(std::vectorint pos) const{pos.resize(rows, -1);for (int i 0; i rows; i){const IndexedValue* ptrRow rowPtr(i);for (int j 0; j count[i]; j){if (ptrRow[j].index i){pos[i] j;break;}}}}int rows, maxCols;std::vectorIndexedValue buf;std::vectorint count; /*记录row行插入的值的个数*/IndexedValue* data;private:SparseMat(const SparseMat);SparseMat operator(const SparseMat);
};/*
得到融合后的图像即图像重建算法函数
x
*/
void solve(const IndexedValue* A, const int* length, const int* diagPos,const double* b, double* x, int rows, int cols, int maxIters, double eps)
{/*rows为要改变的像素点的个数 676cols 8maxIters 10000eps 0.01求解矩阵x的算法Gauss-Sidel*/for (int iter 0; iter maxIters; iter){int count 0;for (int i 0; i rows; i){double val 0;const IndexedValue* ptrRow A cols * i;for (int j 0; j diagPos[i]; j){val ptrRow[j].value * x[ptrRow[j].index];}for (int j diagPos[i] 1; j length[i]; j){val ptrRow[j].value * x[ptrRow[j].index];}val b[i] - val;val / ptrRow[diagPos[i]].value;if (fabs(val - x[i]) eps)count;x[i] val;}if (count rows){printf(converge iter count %d, end\n, iter 1);break;}}
}void makeIndex(const cv::Mat mask, cv::Mat index, int numElems)
{CV_Assert(mask.data mask.type() CV_8UC1);int rows mask.rows, cols mask.cols;index.create(rows, cols, CV_32SC1);index.setTo(-1);int count 0;for (int i 0; i rows; i){const unsigned char* ptrMaskRow mask.ptrunsigned char(i);int* ptrIndexRow index.ptrint(i);for (int j 0; j cols; j){if (ptrMaskRow[j])ptrIndexRow[j] (count);}}numElems count; // 记录mask图片中可改变的像素点的个数
}void draw(const std::vectorcv::Point contour, const cv::Size imageSize,cv::Rect extendRect, cv::Mat mask)
{cv::Rect contourRect cv::boundingRect(contour);int left, right, top, bottom;left contourRect.x;right contourRect.x contourRect.width;top contourRect.y;bottom contourRect.y contourRect.height;CV_Assert(left 0);left--;CV_Assert(right imageSize.width);right;CV_Assert(top 0);top--;CV_Assert(bottom imageSize.height);bottom;extendRect.x left;extendRect.y top;extendRect.width right - left;extendRect.height bottom - top;mask.create(extendRect.height, extendRect.width, CV_8UC1);mask.setTo(0);std::vectorstd::vectorcv::Point contours(1);contours[0] contour;cv::drawContours(mask, contours, -1, cv::Scalar(255), -1, 8,cv::noArray(), 0, cv::Point(-left, -top));
}void draw(const std::vectorcv::Point contour, cv::Size size, cv::Mat mask)
{mask.create(size, CV_8UC1);mask.setTo(0);std::vectorstd::vectorcv::Point contours(1);contours[0] contour;cv::drawContours(mask, contours, -1, cv::Scalar(255), -1, 8, cv::noArray(), 0);
}/*
得到
A 稀疏矩阵
b 融合然后图像的散度
*/
void getEquation(const cv::Mat src, const cv::Mat dst,const cv::Mat mask, const cv::Mat index, int count,SparseMat A, cv::Mat b, cv::Mat x, bool mixGrad false)
{CV_Assert(src.data dst.data mask.data index.data);CV_Assert((src.type() CV_8UC1) (dst.type() CV_8UC1) (mask.type() CV_8UC1) (index.type() CV_32SC1));CV_Assert((src.size() dst.size()) (src.size() mask.size()) (src.size() index.size()));int rows src.rows, cols src.cols;A.create(count, 8);b.create(count, 1, CV_64FC1);b.setTo(0);x.create(count, 1, CV_64FC1);x.setTo(0);for (int i 0; i rows; i){for (int j 0; j cols; j){if (mask.atunsigned char(i, j)){int currIndex index.atint(i, j);int currSrcVal src.atunsigned char(i, j);int currDstVal dst.atunsigned char(i, j);int neighborCount 0;int bVal 0;if (i 0){neighborCount;if (mask.atunsigned char(i - 1, j)){int topIndex index.atint(i - 1, j);A.insert(currIndex, topIndex, -1);}else{bVal dst.atunsigned char(i - 1, j);}if (mixGrad){int srcGrad currSrcVal - src.atunsigned char(i - 1, j);int dstGrad currDstVal - dst.atunsigned char(i - 1, j);bVal (abs(srcGrad) abs(dstGrad) ? srcGrad : dstGrad);}elsebVal (currSrcVal - src.atunsigned char(i - 1, j));}if (i rows - 1){neighborCount;if (mask.atunsigned char(i 1, j)){int bottomIndex index.atint(i 1, j);A.insert(currIndex, bottomIndex, -1);}else{bVal dst.atunsigned char(i 1, j);}if (mixGrad){int srcGrad currSrcVal - src.atunsigned char(i 1, j);int dstGrad currDstVal - dst.atunsigned char(i 1, j);bVal (abs(srcGrad) abs(dstGrad) ? srcGrad : dstGrad);}elsebVal (currSrcVal - src.atunsigned char(i 1, j));}if (j 0){neighborCount;if (mask.atunsigned char(i, j - 1)){int leftIndex index.atint(i, j - 1);A.insert(currIndex, leftIndex, -1);}else{bVal dst.atunsigned char(i, j - 1);}if (mixGrad){int srcGrad currSrcVal - src.atunsigned char(i, j - 1);int dstGrad currDstVal - dst.atunsigned char(i, j - 1);bVal (abs(srcGrad) abs(dstGrad) ? srcGrad : dstGrad);}elsebVal (currSrcVal - src.atunsigned char(i, j - 1));}if (j cols - 1){neighborCount;if (mask.atunsigned char(i, j 1)){int rightIndex index.atint(i, j 1);A.insert(currIndex, rightIndex, -1);}else{bVal dst.atunsigned char(i, j 1);}if (mixGrad){int srcGrad currSrcVal - src.atunsigned char(i, j 1);int dstGrad currDstVal - dst.atunsigned char(i, j 1);bVal (abs(srcGrad) abs(dstGrad) ? srcGrad : dstGrad);}elsebVal (currSrcVal - src.atunsigned char(i, j 1));}A.insert(currIndex, currIndex, neighborCount);b.atdouble(currIndex) bVal;x.atdouble(currIndex) currSrcVal;//x.atdouble(currIndex) dst.atunsigned char(i, j);}}}}/*
该函数把val的像素值复制到dst中
*/
void copy(const cv::Mat val, const cv::Mat mask, const cv::Mat index, cv::Mat dst)
{CV_Assert(val.data val.type() CV_64FC1);CV_Assert(mask.data index.data dst.data);CV_Assert((mask.type() CV_8UC1) (index.type() CV_32SC1) (dst.type() CV_8UC1));CV_Assert((mask.size() index.size()) (mask.size() dst.size()));int rows mask.rows, cols mask.cols;for (int i 0; i rows; i){const unsigned char* ptrMaskRow mask.ptrunsigned char(i);const int* ptrIndexRow index.ptrint(i);unsigned char* ptrDstRow dst.ptrunsigned char(i);for (int j 0; j cols; j){if (ptrMaskRow[j]){ptrDstRow[j] cv::saturate_castunsigned char(val.atdouble(ptrIndexRow[j]));}}}
}//得到一个图片的非零边界
cv::Rect getNonZeroBoundingRectExtendOnePixel(const cv::Mat mask)
{CV_Assert(mask.data mask.type() CV_8UC1);int rows mask.rows, cols mask.cols;int top rows, bottom -1, left cols, right -1;for (int i 0; i rows; i){if (cv::countNonZero(mask.row(i))){top i;break;}}for (int i rows - 1; i 0; i--){if (cv::countNonZero(mask.row(i))){bottom i;break;}}for (int i 0; i cols; i){if (cv::countNonZero(mask.col(i))){left i;break;}}for (int i cols - 1; i 0; i--){if (cv::countNonZero(mask.col(i))){right i;break;}}CV_Assert(top 0 top rows - 1 bottom 0 bottom rows - 1 left 0 left cols - 1 right 0 right cols - 1);return cv::Rect(left - 1, top - 1, right - left 3, bottom - top 3);
}/*!
The basic Poisson image editing function.
Source image, mask image and destination image should have the same size.
Source images content inside the masks non zero region will be blended into
the destination image, using Possion image editing algorithm.
\param[in] src Source image, should be of type CV_8UC1 or CV_8UC3.
\param[in] mask Source images mask. Source images content inside the masks
non zero region will be blended into the destination image.
The masks non zero region should not include the boundaries,
i.e., left most and right most columns and top most and
bottom most columns, otherwise the result may be incorrect.
\param[in,out] dst Destination image, should be the same cv::Mat::type() as
the source image.
\param[in] mixGrad True to apply mixing gradient operation.
*/
void PoissonImageEdit(const cv::Mat src, const cv::Mat mask, cv::Mat dst, bool mixGrad false)
{CV_Assert(src.data mask.data dst.data);CV_Assert(src.size() mask.size() mask.size() dst.size());CV_Assert(src.type() CV_8UC1 || src.type() CV_8UC3);CV_Assert(dst.type() src.type());CV_Assert(mask.type() CV_8UC1);cv::Mat index;SparseMat A; // 稀疏矩阵每行五个非零元素cv::Mat b, x;int numElems; // 将要改变的像素点的个数 makeIndex(mask, index, numElems);if (src.type() CV_8UC1) // 灰色图{getEquation(src, dst, mask, index, numElems, A, b, x, mixGrad);std::vectorint diagPos;A.calcDiagonalElementsPositions(diagPos);solve(A.data, A.count[0], diagPos[0], (double*)b.data, (double*)x.data,A.rows, A.maxCols, 10000, 0.01);copy(x, mask, index, dst);}else if (src.type() CV_8UC3) // 彩色图{cv::Mat srcROISplit[3], dstROISplit[3];for (int i 0; i 3; i){srcROISplit[i].create(src.size(), CV_8UC1);dstROISplit[i].create(dst.size(), CV_8UC1);}cv::split(src, srcROISplit);cv::split(dst, dstROISplit);for (int i 0; i 3; i){getEquation(srcROISplit[i], dstROISplit[i], mask, index, numElems,A, b, x, mixGrad);std::vectorint diagPos;A.calcDiagonalElementsPositions(diagPos);solve(A.data, A.count[0], diagPos[0], (double*)b.data, (double*)x.data,A.rows, A.maxCols, 10000, 0.01);copy(x, mask, index, dstROISplit[i]);}cv::merge(dstROISplit, 3, dst);}
}/*!
Overloaded Poisson image editing function.
Source image and destination image do not need to have the same size.
Source images content inside the contour will be blended into
the destination image, with some magnitude of shifting, using Possion image editing algorithm.
\param[in] src Source image, should be of type CV_8UC1 or CV_8UC3.
\param[in] srcContour A contour indicating the region of interest in the
source image. Pixels inside the region will be blended to
the destination image. The region enclosed by the contour
should not contain pixels on the border of the source image.
\param[in] ofsSrcToDst The offset of the source images region of interest in
the destination image. Pixel (x, y) in the region of interest in
the source image will be blended in (x, y) ofsSrcToDst
in the destination image. You should make sure
that the destination images region of interest locates totally inside
the destionation image excluding the border pixels.
\param[in,out] dst Destination image, should be the same cv::Mat::type() as
the source image.
\param[in] mixGrad True to apply mixing gradient operation.
*/
void PoissonImageEdit(const cv::Mat src, const std::vectorcv::Point srcContour,cv::Point ofsSrcToDst, cv::Mat dst, bool mixGrad false)
{CV_Assert(src.data (src.type() CV_8UC1 || src.type() CV_8UC3));CV_Assert(srcContour.size() 3);CV_Assert(dst.data dst.type() src.type());cv::Mat mask;cv::Rect srcRect;draw(srcContour, src.size(), srcRect, mask);cv::Mat srcROI src(srcRect);cv::Mat dstROI dst(srcRect ofsSrcToDst);PoissonImageEdit(srcROI, mask, dstROI, mixGrad);return;
}/*!
Overloaded Poisson image editing function.
Source image and source mask imageshould have the same size.
Source images content inside the masks non zero region will be blended into
the destination image, with some magnitude of shifting, using Possion image editing algorithm.
\param[in] src Source image, should be of type CV_8UC1 or CV_8UC3.
\param[in] srcMask Source images mask indicating the region of interest in the
source image. Pixels inside the region will be blended to
the destination image. The region enclosed by the contour
should not contain pixels on the border of the source image.
\param[in] ofsSrcToDst The offset of the source images region of interest in
the destination image. Pixel (x, y) in the region of interest in
the source image will be blended in (x, y) ofsSrcToDst
in the destination image. You should make sure
that the destination images region of interest locates totally inside
the destionation image excluding the border pixels.
\param[in,out] dst Destination image, should be the same cv::Mat::type() as
the source image.
\param[in] mixGrad True to apply mixing gradient operation.
*/
void PoissonImageEdit(const cv::Mat src, const cv::Mat srcMask,cv::Point ofsSrcToDst, cv::Mat dst, bool mixGrad false)
{CV_Assert(src.data (src.type() CV_8UC1 || src.type() CV_8UC3));CV_Assert(srcMask.data srcMask.type() CV_8UC1);CV_Assert(dst.data dst.type() src.type());cv::Rect srcRect getNonZeroBoundingRectExtendOnePixel(srcMask);cv::Mat mask srcMask(srcRect);cv::Mat srcROI src(srcRect);//cv::Mat dstROI dst(srcRect ofsSrcToDst);cv::Mat dstROI dst(cv::Rect(0, 0, srcRect.width, srcRect.height) cv::Point(dst.cols / 2 - srcRect.width / 2, dst.rows / 2 - srcRect.height / 2));PoissonImageEdit(srcROI, mask, dstROI, mixGrad);return;
}#define GRAY 0
#define ORDER 6 //测试代码
int main()
{
#if ORDER 0{// Images from http://www.ctralie.com/Teaching/PoissonImageEditing/cv::Mat src cv::imread(GreatWhiteShark.jpg);cv::Mat dst cv::imread(beach.jpg);
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifstd::vectorcv::Point contour(4);contour[0] cv::Point(380, 300) - cv::Point(320, 230);contour[1] cv::Point(550, 300) - cv::Point(320, 230);contour[2] cv::Point(550, 420) - cv::Point(320, 230);contour[3] cv::Point(380, 420) - cv::Point(320, 230);cv::Point ofsSrcToDst cv::Point(320, 230);PoissonImageEdit(src, contour, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result0.jpg, dst);cv::waitKey(0);}
#endif#if ORDER 1{// Eye photo and hand photo from // https://en.wikipedia.org/wiki/Gradient-domain_image_processingcv::Mat src cv::imread(220px-EyePhoto.jpg);cv::Mat dst cv::imread(1074px-HandPhoto.jpg);
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifstd::vectorcv::Point srcContour(4);srcContour[0] cv::Point(1, 1);srcContour[1] cv::Point(218, 1);srcContour[2] cv::Point(218, 130);srcContour[3] cv::Point(1, 130);cv::Point ofsSrcToDst(570, 300);PoissonImageEdit(src, srcContour, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result1.jpg, dst);cv::waitKey(0);}
#endif#if ORDER 2{// Eye photo from // https://en.wikipedia.org/wiki/Gradient-domain_image_processing// Tree photo from // https://commons.wikimedia.org/wiki/File:Big_Tree_with_Red_Sky_in_the_Winter_Night.jpg?uselangzh-cncv::Mat src cv::imread(220px-EyePhoto.jpg);cv::Mat dst cv::imread(1024px-Big_Tree_with_Red_Sky_in_the_Winter_Night.jpg);
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifstd::vectorcv::Point srcContour(4);srcContour[0] cv::Point(1, 1);srcContour[1] cv::Point(218, 1);srcContour[2] cv::Point(218, 130);srcContour[3] cv::Point(1, 130);cv::Point ofsSrcToDst(570, 300);PoissonImageEdit(src, srcContour, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result2.jpg, dst);cv::waitKey(0);}
#endif#if ORDER 3// following image sources// http://cs.brown.edu/courses/csci1950-g/results/proj2/pdoran/{cv::Mat src cv::imread(src_img01.jpg);cv::Mat srcMask cv::imread(mask_img01.jpg, cv::IMREAD_GRAYSCALE);cv::Mat dst cv::imread(tar_img01.jpg);
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifcv::Point ofsSrcToDst(200, 200);cv::threshold(srcMask, srcMask, 128, 255, cv::THRESH_BINARY);PoissonImageEdit(src, srcMask, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result3.jpg, dst);cv::waitKey(0);}
#endif#if ORDER 4{cv::Mat src cv::imread(src_img02.jpg);cv::Mat srcMask cv::imread(mask_img02.jpg, cv::IMREAD_GRAYSCALE);cv::Mat dst cv::imread(tar_img02.jpg);
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifcv::Point ofsSrcToDst(20, 200);cv::threshold(srcMask, srcMask, 128, 255, cv::THRESH_BINARY);PoissonImageEdit(src, srcMask, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result4.jpg, dst);cv::waitKey(0);}
#endif#if ORDER 5{cv::Mat src cv::imread(src_img03.jpg);cv::Mat srcMask cv::imread(mask_img03.jpg, cv::IMREAD_GRAYSCALE);cv::Mat dst cv::imread(tar_img03.jpg);
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifcv::Point ofsSrcToDst(20, 20);cv::threshold(srcMask, srcMask, 128, 255, cv::THRESH_BINARY);PoissonImageEdit(src, srcMask, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result5.jpg, dst);cv::waitKey(0);}
#endif#if ORDER 6{cv::Mat src cv::imread(src_img04.jpg);cv::Mat srcMask cv::imread(mask_img04.jpg, cv::IMREAD_GRAYSCALE);cv::Mat dst cv::imread(tar_img04.jpg);if (src.empty() || srcMask.empty() || dst.empty()){cout read image fail!! endl;return -1;}
#if GRAYcv::cvtColor(src, src, cv::COLOR_BGR2GRAY);cv::cvtColor(dst, dst, cv::COLOR_BGR2GRAY);
#endifcv::Point ofsSrcToDst(20, 20);cv::threshold(srcMask, srcMask, 128, 255, cv::THRESH_BINARY);PoissonImageEdit(src, srcMask, ofsSrcToDst, dst, true);cv::imshow(src, src);cv::imshow(dst, dst);cv::imwrite(result6.jpg, dst);cv::waitKey(0);}
#endifreturn 0;
}