日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

泊松融合

發布時間:2024/7/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 泊松融合 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

泊松融合是一種很重要的圖像融合算法,該算法選自論文([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.jpg+mask.jpg重疊下可以顯示的部分(ROI)融合到dst.jpg中,融合到dst.jpg中時,我們需要為ROI設計在dst.jpg的坐標,我們設置為dst.jpg的圖像中心。也就是說,src.jpg+mask.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,最后反向計算出圖像x,x即為最終結果。

    /* 代碼選自: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)處于第幾個位置,用vector<int>pos記錄,pos[i]=0,1,2,三個數字之一*/void calcDiagonalElementsPositions(std::vector<int>& 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::vector<IndexedValue> buf;std::vector<int> 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.ptr<unsigned char>(i);int* ptrIndexRow = index.ptr<int>(i);for (int j = 0; j < cols; j++){if (ptrMaskRow[j])ptrIndexRow[j] = (count++);}}numElems = count; // 記錄mask圖片中,可改變的像素點的個數 }void draw(const std::vector<cv::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::vector<std::vector<cv::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::vector<cv::Point>& contour, cv::Size& size, cv::Mat& mask) {mask.create(size, CV_8UC1);mask.setTo(0);std::vector<std::vector<cv::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.at<unsigned char>(i, j)){int currIndex = index.at<int>(i, j);int currSrcVal = src.at<unsigned char>(i, j);int currDstVal = dst.at<unsigned char>(i, j);int neighborCount = 0;int bVal = 0;if (i > 0){neighborCount++;if (mask.at<unsigned char>(i - 1, j)){int topIndex = index.at<int>(i - 1, j);A.insert(currIndex, topIndex, -1);}else{bVal += dst.at<unsigned char>(i - 1, j);}if (mixGrad){int srcGrad = currSrcVal - src.at<unsigned char>(i - 1, j);int dstGrad = currDstVal - dst.at<unsigned char>(i - 1, j);bVal += (abs(srcGrad) > abs(dstGrad) ? srcGrad : dstGrad);}elsebVal += (currSrcVal - src.at<unsigned char>(i - 1, j));}if (i < rows - 1){neighborCount++;if (mask.at<unsigned char>(i + 1, j)){int bottomIndex = index.at<int>(i + 1, j);A.insert(currIndex, bottomIndex, -1);}else{bVal += dst.at<unsigned char>(i + 1, j);}if (mixGrad){int srcGrad = currSrcVal - src.at<unsigned char>(i + 1, j);int dstGrad = currDstVal - dst.at<unsigned char>(i + 1, j);bVal += (abs(srcGrad) > abs(dstGrad) ? srcGrad : dstGrad);}elsebVal += (currSrcVal - src.at<unsigned char>(i + 1, j));}if (j > 0){neighborCount++;if (mask.at<unsigned char>(i, j - 1)){int leftIndex = index.at<int>(i, j - 1);A.insert(currIndex, leftIndex, -1);}else{bVal += dst.at<unsigned char>(i, j - 1);}if (mixGrad){int srcGrad = currSrcVal - src.at<unsigned char>(i, j - 1);int dstGrad = currDstVal - dst.at<unsigned char>(i, j - 1);bVal += (abs(srcGrad) > abs(dstGrad) ? srcGrad : dstGrad);}elsebVal += (currSrcVal - src.at<unsigned char>(i, j - 1));}if (j < cols - 1){neighborCount++;if (mask.at<unsigned char>(i, j + 1)){int rightIndex = index.at<int>(i, j + 1);A.insert(currIndex, rightIndex, -1);}else{bVal += dst.at<unsigned char>(i, j + 1);}if (mixGrad){int srcGrad = currSrcVal - src.at<unsigned char>(i, j + 1);int dstGrad = currDstVal - dst.at<unsigned char>(i, j + 1);bVal += (abs(srcGrad) > abs(dstGrad) ? srcGrad : dstGrad);}elsebVal += (currSrcVal - src.at<unsigned char>(i, j + 1));}A.insert(currIndex, currIndex, neighborCount);b.at<double>(currIndex) = bVal;x.at<double>(currIndex) = currSrcVal;//x.at<double>(currIndex) = dst.at<unsigned 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.ptr<unsigned char>(i);const int* ptrIndexRow = index.ptr<int>(i);unsigned char* ptrDstRow = dst.ptr<unsigned char>(i);for (int j = 0; j < cols; j++){if (ptrMaskRow[j]){ptrDstRow[j] = cv::saturate_cast<unsigned char>(val.at<double>(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 image's content inside the mask's 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 image's mask. Source image's content inside the mask's non zero region will be blended into the destination image. The mask's 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::vector<int> 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::vector<int> 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 image's 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 image's 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 image's 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::vector<cv::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 image's content inside the mask's 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 image's 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 image's 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 image's 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::vector<cv::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::vector<cv::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?uselang=zh-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::vector<cv::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; }

    總結

    以上是生活随笔為你收集整理的泊松融合的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。