OpenCV小项目:图像融合(泊松融合—Possion Blending)
原理
太多了,看这些博客吧
主要参考博客1: http://blog.csdn.net/hjimce/article/details/45716603
主要参考博客2: http://blog.csdn.net/wd1603926823/article/details/49867069
主要参考博客3: http://blog.csdn.net/baimafujinji/article/details/46787837
代码示例
#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h> using namespace std;
using namespace cv;#define elif else if
#define ATD at<double>// 图像水平梯度的正向计算,即img(i,j+1)-img(i,j)
// img:要计算其梯度的图像
Mat getGradientXp(Mat &img)
{int height = img.rows;int width = img.cols;Mat casimg = repeat(img, 1, 2); // repeat the input img for two times, they are horizontally arranged.Rect roi = Rect(1, 0, width, height);Mat roimat = casimg(roi); // roimat is the version of img that the first column is in the last one, the other columns move one column forward.return roimat - img; // img(i, j + 1) - img(i, j)
}// 图像垂直梯度的正向计算,即img(i+1,j)-img(i,j)
// img:要计算其梯度的图像
Mat getGradientYp(Mat &img)
{int height = img.rows;int width = img.cols;Mat casimg = repeat(img, 2, 1); // repeat the input img for two times, they are vertically arranged.Rect roi = Rect(0, 1, width, height);Mat roimat = casimg(roi); // roimat is the version of img that the first row is in the last one, the other rows move one row forward.return roimat - img; // img(i + 1, j) - img(i, j)
}// 图像水平梯度的负向计算,即img(i,j-1)-img(i,j)
// img:要计算其梯度的图像
Mat getGradientXn(Mat &img) {int height = img.rows;int width = img.cols;Mat casimg = repeat(img, 1, 2); // repeat the input img for two times, they are horizontally arranged.Rect roi = Rect(width - 1, 0, width, height);Mat roimat = casimg(roi); // roimat is the version of img that the last column is in the first one, the other columns move one column backward.return roimat - img; // img(i, j - 1) - img(i, j)
}// 图像垂直梯度的负向计算,即img(i-1,j)-img(i,j)
// img:要计算其梯度的图像
Mat getGradientYn(Mat &img)
{int height = img.rows;int width = img.cols;Mat casimg = repeat(img, 2, 1); // repeat the input img for two times, they are vertically arranged.Rect roi = Rect(0, height - 1, width, height);Mat roimat = casimg(roi); // roimat is the version of img that the last row is in the first one, the other rows move one row backward.return roimat - img; // img(i - 1, j) - img(i, j)
}int getLabel(int i, int j, int height, int width)
{return i * width + j; // i is in height axis; j is in width axis.
}// 得到矩阵A
Mat getA(int height, int width)
{Mat A = Mat::eye(height * width, height * width, CV_64FC1);A *= -4;// M: the label matrix of roi from im2; divede M into three parts, 0,1,2, respectively.// 0: the corners of roi// 1: boundaries but not corners// 2: inner part of roi// different parts represent different methods to asssign A valuesMat M = Mat::zeros(height, width, CV_64FC1);Mat temp = Mat::ones(height, width - 2, CV_64FC1);Rect roi = Rect(1, 0, width - 2, height);Mat roimat = M(roi);temp.copyTo(roimat);temp = Mat::ones(height - 2, width, CV_64FC1);roi = Rect(0, 1, width, height - 2);roimat = M(roi);temp.copyTo(roimat);temp = Mat::ones(height - 2, width - 2, CV_64FC1);temp *= 2;roi = Rect(1, 1, width - 2, height - 2);roimat = M(roi);temp.copyTo(roimat);// get Matrix Afor (int i = 0; i < height; i++) {for (int j = 0; j < width; j++) {// get index of M(i,j)int label = getLabel(i, j, height, width);// when M(i,j) is the corner, assign coeffients to Aif (M.ATD(i, j) == 0){if (i == 0) A.ATD(getLabel(i + 1, j, height, width), label) = 1; // left upperelif(i == height - 1) A.ATD(getLabel(i - 1, j, height, width), label) = 1; // right upperif (j == 0) A.ATD(getLabel(i, j + 1, height, width), label) = 1; // left lowerelif(j == width - 1) A.ATD(getLabel(i, j - 1, height, width), label) = 1; // right lower}// when M(i,j) is the boundary but not corner, assign coeffients to Aelif(M.ATD(i, j) == 1){if (i == 0) {A.ATD(getLabel(i + 1, j, height, width), label) = 1;A.ATD(getLabel(i, j - 1, height, width), label) = 1;A.ATD(getLabel(i, j + 1, height, width), label) = 1;}elif(i == height - 1) {A.ATD(getLabel(i - 1, j, height, width), label) = 1;A.ATD(getLabel(i, j - 1, height, width), label) = 1;A.ATD(getLabel(i, j + 1, height, width), label) = 1;}if (j == 0) {A.ATD(getLabel(i, j + 1, height, width), label) = 1;A.ATD(getLabel(i - 1, j, height, width), label) = 1;A.ATD(getLabel(i + 1, j, height, width), label) = 1;}elif(j == width - 1) {A.ATD(getLabel(i, j - 1, height, width), label) = 1;A.ATD(getLabel(i - 1, j, height, width), label) = 1;A.ATD(getLabel(i + 1, j, height, width), label) = 1;}}// when M(i,j) is the inner point, assign coeffients to Aelse {A.ATD(getLabel(i, j - 1, height, width), label) = 1;A.ATD(getLabel(i, j + 1, height, width), label) = 1;A.ATD(getLabel(i - 1, j, height, width), label) = 1;A.ATD(getLabel(i + 1, j, height, width), label) = 1;}}}return A;
}// 计算b
// 使用getGradient函数。
Mat getB2(Mat &img1, Mat &img2, int posX, int posY, Rect ROI)
{// calculate the divergence of img1Mat MergeGradXp = getGradientXp(img1);Mat GradXp2 = getGradientXp(img2);Mat MergeGradXpROI = MergeGradXp(ROI);GradXp2.copyTo(MergeGradXpROI);Mat MergeGradXn = getGradientXn(img1);Mat GradXn2 = getGradientXn(img2);Mat MergeGradXnROI = MergeGradXn(ROI);GradXn2.copyTo(MergeGradXnROI);Mat MergeGradYp = getGradientYp(img1);Mat GradYp2 = getGradientYp(img2);Mat MergeGradYpROI = MergeGradYp(ROI);GradYp2.copyTo(MergeGradYpROI);Mat MergeGradYn = getGradientYn(img1);Mat GradYn2 = getGradientYn(img2);Mat MergeGradYnROI = MergeGradYn(ROI);GradYn2.copyTo(MergeGradYnROI);Mat grad = MergeGradXp + MergeGradXn + MergeGradYp + MergeGradYn;int roiheight = ROI.height;int roiwidth = ROI.width;Mat B = Mat::zeros(roiheight * roiwidth, 1, CV_64FC1);for (int i = 0; i < roiheight; i++) {for (int j = 0; j < roiwidth; j++) {double temp = 0.0;temp += grad.ATD(i + ROI.y, j + ROI.x);if (i == 0) temp -= img2.ATD(i - 1 + posY, j + posX);if (i == roiheight - 1) temp -= img2.ATD(i + 1 + posY, j + posX);if (j == 0) temp -= img2.ATD(i + posY, j - 1 + posX);if (j == roiwidth - 1) temp -= img2.ATD(i + posY, j + 1 + posX);B.ATD(getLabel(i, j, roiheight, roiwidth), 0) = temp;}}return B;
}// 求解方程,并将其重塑为正确的高度和宽度。
// Solve equation and reshape it back to the right height and width.
Mat getResult(Mat &A, Mat &B, Rect &ROI) {Mat result;solve(A, B, result);result = result.reshape(0, ROI.height);return result;
}/// 泊松混合
// 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
Mat poisson_blending(Mat &img1, Mat &img2, Rect ROI, int posX, int posY)
{int roiheight = ROI.height;int roiwidth = ROI.width;Mat A = getA(roiheight, roiwidth);// we must do the poisson blending to each channel.vector<Mat> rgb1;split(img1, rgb1);vector<Mat> rgb2;split(img2, rgb2);vector<Mat> result;Mat merged, res, Br, Bg, Bb;Br = getB2(rgb1[0], rgb2[0], posX, posY, ROI);res = getResult(A, Br, ROI);result.push_back(res);cout << "R channel finished..." << endl;Bg = getB2(rgb1[1], rgb2[1], posX, posY, ROI);res = getResult(A, Bg, ROI);result.push_back(res);cout << "G channel finished..." << endl;Bb = getB2(rgb1[2], rgb2[2], posX, posY, ROI);res = getResult(A, Bb, ROI);result.push_back(res);cout << "B channel finished..." << endl;// merge the 3 gray images into a 3-channel image merge(result, merged);return merged;
}int main(int argc, char** argv)
{Mat img1, img2;Mat in1 = imread("./image/niao.jpg");Mat in2 = imread("./image/park.jpg");imshow("src", in1);imshow("dst", in2);in1.convertTo(img1, CV_64FC3);in2.convertTo(img2, CV_64FC3);Rect rc = Rect(50, 62, 74, 38);//the part in im2 that we wanna move into im1// 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 img2Mat result = poisson_blending(img1, img2, rc, 90, 60);result.convertTo(result, CV_8UC1);Rect rc2 = Rect(400, 50, 74, 38);Mat roimat = in2(rc2);result.copyTo(roimat);imshow("roi", result);imshow("result", in2);imwrite("./image/niao_park.jpg", in2);waitKey(0);return 0;
}
OpenCV小项目:图像融合(泊松融合—Possion Blending)相关推荐
- 泊松图像融合(泊松融合)
泊松图像融合(泊松融合) from: http://blog.csdn.net/baimafujinji/article/details/46787837 在之前的文章中,我们详细介绍了基于泊松方程的 ...
- python+opencv别踩白块儿游戏辅助,一天一个opencv小项目(已开源)
python+opencv别踩白块儿游戏辅助,一天一个opencv小项目(已开源) 见链接
- 10 个开源 Python OpenCV 小项目,YouTube热门
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自 | 新机器视觉 1. Drowsiness Detect ...
- opencv实践项目-图像卡通化
目录 1.如何使图像卡通画 2.铅笔素描滤波器 3. 细节增强滤波器 4. 双边过滤器 5. 铅笔边缘滤波器 1.如何使图像卡通画 我们通常需要执行两个主要步骤将图像转换为卡通图像:边缘检测和区域平滑 ...
- C/C++,Qt,Python,OpenCV小项目实战-实时桌面颜色查询
源码连接如下(含Qt,VS,Python) https://download.csdn.net/download/qq78442761/10723417 程序运行截图如下: (原理)逻辑如下: 1.使 ...
- 【Opencv小项目 1】Opencv实现简单颜色识别
参考 Opencv简单颜色识别 Youtube教学视频 BGR HSV颜色模型 步骤 一. BGR 和 HSV 颜色模型 BGR Model BGR模型表示三种颜色通道:红.绿.蓝,采用BGR模型的图 ...
- opencv 泊松融合
图像融合简介 图像融合(Image Fusion)是指将多源信道所采集到的关于同一目标的图像数据经过图像处理和计算机技术等,最大限度的提取各自信道中的有利信息,最后综合成高质量的图像,以提高图像信息的 ...
- 泊松融合进阶——DFT求解二维泊松方程
前言 泊松融合(Poisson Blending)是图像处理领域著名的图像融合算法,自从2003年发表以来,有很多基于此算法的应用和改进研究出现.泊松融合无需像Alpha blending一样的精确抠 ...
- 计算机视觉预备知识,计算机视觉:泊松融合
Poisson Blending4:更多用途 Poisson Blending0:预备知识(图像的梯度.泊松方程) 进入正题之前,我们先补充一下基础知识.图像的梯度 什么是图像的梯度?我们可以把图像看 ...
最新文章
- 什么是URL?协议头,路径和端口是什么意思?
- oracle存储过程00054,oracle执行存储过程报错:ORA-12011
- 在不同制作基础上该如何选择网页制作软件?
- SharePoint Explorer View
- 离散数学及其应用傅彦pdf_《离散数学及其应用》第二章 计算与探索
- 机器学习算法在用户行为检测(UBA)领域的应用
- 2021年最好用的5个股票API
- Windows 0day成功验证之ETERNALBLUE 本帖由春秋首发~作者:神风 @春秋文阁负责人 方程式又一波0day【该贴有工具】:https://bbs.ichunqiu.com/thr
- 我的五年百度博客文章列表(带链接版)
- NanobeamM5无线网桥配置
- 安防摄像头移动侦测和遮挡侦测基本原理
- Chrome浏览器取证分析
- linux(ubuntu)下实现鼠标侧键映射双击、鼠标中键 快捷键的方法—— 使用xbindkeys
- 关于 人工智能的理解
- iOS 百度地图之坐标转换
- Primo.Ramdisk.Srv.Mui.Setup安装配置教程
- 转载《利用Windows系统自带命令手工搞定病毒》_原水_新浪博客
- mysql 1亿条数据建索引时间_单表 13 亿记录创建索引需要多长时间?
- h5在线制作html5,在线制作HTML5多媒体作品的技巧
- 为什么下载小电影时,进度经常会卡在99%?