├── ImgViewer ├── ImgViewer.pro ├── ImgViewer.pro.user ├── geometryalg.cpp ├── geometryalg.h ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── qimageshowwidget.cpp └── qimageshowwidget.h ├── README.md ├── README_IMG ├── 1.PNG ├── 2.PNG ├── 3.PNG ├── 4.PNG ├── 5.PNG ├── 6.PNG ├── 7.jpg └── 8.PNG ├── data ├── source.jpg └── target.jpg ├── mvc-final-opt.pdf └── 论文翻译.doc /ImgViewer/ImgViewer.pro: -------------------------------------------------------------------------------- 1 | QT += core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | CONFIG += c++11 6 | CONFIG += console 7 | 8 | QMAKE_CXXFLAGS+=/openmp 9 | 10 | # The following define makes your compiler emit warnings if you use 11 | # any Qt feature that has been marked deprecated (the exact warnings 12 | # depend on your compiler). Please consult the documentation of the 13 | # deprecated API in order to know how to port your code away from it. 14 | DEFINES += QT_DEPRECATED_WARNINGS 15 | 16 | # You can also make your code fail to compile if it uses deprecated APIs. 17 | # In order to do so, uncomment the following line. 18 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 19 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 20 | 21 | SOURCES += \ 22 | geometryalg.cpp \ 23 | main.cpp \ 24 | mainwindow.cpp \ 25 | qimageshowwidget.cpp 26 | 27 | HEADERS += \ 28 | geometryalg.h \ 29 | mainwindow.h \ 30 | qimageshowwidget.h 31 | 32 | FORMS += \ 33 | mainwindow.ui 34 | 35 | # Default rules for deployment. 36 | qnx: target.path = /tmp/$${TARGET}/bin 37 | else: unix:!android: target.path = /opt/$${TARGET}/bin 38 | !isEmpty(target.path): INSTALLS += target 39 | 40 | INCLUDEPATH += D:/SoftWare/OpenCV/opencv/build/include \ 41 | D:/Work/CGALBuild/CGAL-4.14.3/include D:/SoftWare/boost_1_72_0 \ 42 | D:/Work/CGALBuild/CGAL-4.14.3/Build/include \ 43 | D:/Work/CGALBuild/CGAL-4.14.3/auxiliary/gmp/include 44 | 45 | LIBS += -LD:/SoftWare/OpenCV/opencv/build/x64/vc15/lib/ -lopencv_world345 \ 46 | -LD:/Work/CGALBuild/CGAL-4.14.3/Build/lib -lCGAL_Core-vc141-mt-4.14.3 -lCGAL-vc141-mt-4.14.3 \ 47 | -LD:/Work/CGALBuild/CGAL-4.14.3/auxiliary/gmp/lib -llibgmp-10 48 | 49 | #DESTDIR = $$PWD/../bin 50 | -------------------------------------------------------------------------------- /ImgViewer/ImgViewer.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {827e885d-279e-435a-a503-f857c38e58aa} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | GB18030 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | -fno-delayed-template-parsing 60 | 61 | false 62 | {6135a49d-0736-4083-8de1-470c7113255d} 63 | 64 | 65 | 66 | ProjectExplorer.Project.Target.0 67 | 68 | Desktop Qt 5.12.5 MSVC2017 64bit 69 | Desktop Qt 5.12.5 MSVC2017 64bit 70 | qt.qt5.5125.win64_msvc2017_64_kit 71 | 1 72 | 0 73 | 0 74 | 75 | D:/Work/MVCImageBlend/build-ImgViewer-Desktop_Qt_5_12_5_MSVC2017_64bit-Debug 76 | 77 | 78 | true 79 | qmake 80 | 81 | QtProjectManager.QMakeBuildStep 82 | true 83 | 84 | false 85 | false 86 | false 87 | 88 | 89 | true 90 | Make 91 | 92 | Qt4ProjectManager.MakeStep 93 | 94 | false 95 | 96 | 97 | false 98 | 99 | 2 100 | Build 101 | 102 | ProjectExplorer.BuildSteps.Build 103 | 104 | 105 | 106 | true 107 | Make 108 | 109 | Qt4ProjectManager.MakeStep 110 | 111 | true 112 | clean 113 | 114 | false 115 | 116 | 1 117 | Clean 118 | 119 | ProjectExplorer.BuildSteps.Clean 120 | 121 | 2 122 | false 123 | 124 | Debug 125 | Debug 126 | Qt4ProjectManager.Qt4BuildConfiguration 127 | 2 128 | true 129 | 130 | 131 | D:/Work/MVCImageBlend/build-ImgViewer-Desktop_Qt_5_12_5_MSVC2017_64bit-Release 132 | 133 | 134 | true 135 | qmake 136 | 137 | QtProjectManager.QMakeBuildStep 138 | false 139 | 140 | false 141 | false 142 | true 143 | 144 | 145 | true 146 | Make 147 | 148 | Qt4ProjectManager.MakeStep 149 | 150 | false 151 | 152 | 153 | false 154 | 155 | 2 156 | Build 157 | 158 | ProjectExplorer.BuildSteps.Build 159 | 160 | 161 | 162 | true 163 | Make 164 | 165 | Qt4ProjectManager.MakeStep 166 | 167 | true 168 | clean 169 | 170 | false 171 | 172 | 1 173 | Clean 174 | 175 | ProjectExplorer.BuildSteps.Clean 176 | 177 | 2 178 | false 179 | 180 | Release 181 | Release 182 | Qt4ProjectManager.Qt4BuildConfiguration 183 | 0 184 | true 185 | 186 | 187 | D:/Work/MVCImageBlend/build-ImgViewer-Desktop_Qt_5_12_5_MSVC2017_64bit-Profile 188 | 189 | 190 | true 191 | qmake 192 | 193 | QtProjectManager.QMakeBuildStep 194 | true 195 | 196 | false 197 | true 198 | true 199 | 200 | 201 | true 202 | Make 203 | 204 | Qt4ProjectManager.MakeStep 205 | 206 | false 207 | 208 | 209 | false 210 | 211 | 2 212 | Build 213 | 214 | ProjectExplorer.BuildSteps.Build 215 | 216 | 217 | 218 | true 219 | Make 220 | 221 | Qt4ProjectManager.MakeStep 222 | 223 | true 224 | clean 225 | 226 | false 227 | 228 | 1 229 | Clean 230 | 231 | ProjectExplorer.BuildSteps.Clean 232 | 233 | 2 234 | false 235 | 236 | Profile 237 | Profile 238 | Qt4ProjectManager.Qt4BuildConfiguration 239 | 0 240 | true 241 | 242 | 3 243 | 244 | 245 | 0 246 | 部署 247 | 248 | ProjectExplorer.BuildSteps.Deploy 249 | 250 | 1 251 | Deploy Configuration 252 | 253 | ProjectExplorer.DefaultDeployConfiguration 254 | 255 | 1 256 | 257 | 258 | dwarf 259 | 260 | cpu-cycles 261 | 262 | 263 | 250 264 | -F 265 | true 266 | 4096 267 | false 268 | false 269 | 1000 270 | 271 | true 272 | 273 | false 274 | false 275 | false 276 | false 277 | true 278 | 0.01 279 | 10 280 | true 281 | kcachegrind 282 | 1 283 | 25 284 | 285 | 1 286 | true 287 | false 288 | true 289 | valgrind 290 | 291 | 0 292 | 1 293 | 2 294 | 3 295 | 4 296 | 5 297 | 6 298 | 7 299 | 8 300 | 9 301 | 10 302 | 11 303 | 12 304 | 13 305 | 14 306 | 307 | 2 308 | 309 | ImgViewer 310 | 311 | Qt4ProjectManager.Qt4RunConfiguration:D:/Work/MVCImageBlend/ImgViewer/ImgViewer.pro 312 | 313 | 3768 314 | false 315 | true 316 | true 317 | false 318 | false 319 | true 320 | true 321 | 322 | D:/Work/MVCImageBlend/build-ImgViewer-Desktop_Qt_5_12_5_MSVC2017_64bit-Release 323 | 324 | 1 325 | 326 | 327 | 328 | ProjectExplorer.Project.TargetCount 329 | 1 330 | 331 | 332 | ProjectExplorer.Project.Updater.FileVersion 333 | 22 334 | 335 | 336 | Version 337 | 22 338 | 339 | 340 | -------------------------------------------------------------------------------- /ImgViewer/geometryalg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/ImgViewer/geometryalg.cpp -------------------------------------------------------------------------------- /ImgViewer/geometryalg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/ImgViewer/geometryalg.h -------------------------------------------------------------------------------- /ImgViewer/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication a(argc, argv); 8 | MainWindow w; 9 | w.show(); 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /ImgViewer/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | 4 | MainWindow::MainWindow(QWidget *parent) 5 | : QMainWindow(parent) 6 | , ui(new Ui::MainWindow) 7 | { 8 | ui->setupUi(this); 9 | } 10 | 11 | MainWindow::~MainWindow() 12 | { 13 | delete ui; 14 | } 15 | 16 | 17 | void MainWindow::on_action_triggered() 18 | { 19 | const char* imagePath = "D:/Work/MVCImageBlend/data/source.jpg"; 20 | ui->imageShowWidget->LoadImage(imagePath); 21 | } 22 | 23 | void MainWindow::on_actionBlend_triggered() 24 | { 25 | const char* imagePath = "D:/Work/MVCImageBlend/data/target.jpg"; 26 | 27 | int posX = 370; 28 | int posY = 290; 29 | ui->imageShowWidget->ImageBlend(imagePath, posX, posY); 30 | } 31 | 32 | void MainWindow::on_actiondraw_triggered(bool checked) 33 | { 34 | ui->imageShowWidget->SetDraw(checked); 35 | } 36 | -------------------------------------------------------------------------------- /ImgViewer/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | QT_BEGIN_NAMESPACE 7 | namespace Ui { class MainWindow; } 8 | QT_END_NAMESPACE 9 | 10 | class MainWindow : public QMainWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | MainWindow(QWidget *parent = nullptr); 16 | ~MainWindow(); 17 | 18 | private slots: 19 | void on_action_triggered(); 20 | 21 | void on_actionBlend_triggered(); 22 | 23 | void on_actiondraw_triggered(bool checked); 24 | 25 | private: 26 | Ui::MainWindow *ui; 27 | }; 28 | #endif // MAINWINDOW_H 29 | -------------------------------------------------------------------------------- /ImgViewer/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1000 10 | 800 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 0 20 | 21 | 22 | 0 23 | 24 | 25 | 0 26 | 27 | 28 | 0 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | toolBar 39 | 40 | 41 | TopToolBarArea 42 | 43 | 44 | false 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 打开 53 | 54 | 55 | 56 | 57 | 融合 58 | 59 | 60 | 61 | 62 | true 63 | 64 | 65 | 绘制 66 | 67 | 68 | 69 | 70 | 71 | QImageShowWidget 72 | QWidget 73 |
qimageshowwidget.h
74 | 1 75 |
76 |
77 | 78 | 79 |
80 | -------------------------------------------------------------------------------- /ImgViewer/qimageshowwidget.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/ImgViewer/qimageshowwidget.cpp -------------------------------------------------------------------------------- /ImgViewer/qimageshowwidget.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/ImgViewer/qimageshowwidget.h -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [1. 概述](#1-概述) 2 | 3 | [2. 实现](#2-实现) 4 | - [2.1. 准备](#21-准备) 5 | - [2.2. 核心](#22-核心) 6 | - [2.2.1. 均值坐标(Mean-Value Coordinates)](#221-均值坐标mean-value-coordinates) 7 | - [2.2.2. ROI边界栅格化](#222-roi边界栅格化) 8 | - [2.2.3. 核心实现](#223-核心实现) 9 | - [2.2.4. 实现中的问题](#224-实现中的问题) 10 | 11 | [3. 效果](#3-效果) 12 | - [3.1. 使用过程](#31-使用过程) 13 | - [3.2. 效率](#32-效率) 14 | 15 | [4. 参考](#4-参考) 16 | 17 | # 1. 概述 18 | 泊松融合是图像融合处理效果最好的算法,其来自于2004年Siggraph的经典paper:《Poisson Image Editing》。以这篇文章为发端,很多大神提出了一系列的优化算法。2009年, Zeev Farbman 在的SIGGRAPH上面提出的基于Mean-Value Coordinates方法的泊松融合加速算法《Coordinates for Instant Image Cloning》(文献二)。在这篇文章中,泊松方程被转换成拉普拉斯方程,并且提出了用均值坐标Mean-Value Coordinates来近似求解这个方程,从而达到实时运算的效果。 19 | 20 | 初步了解了一下原生的泊松融合算法和均值坐标融合算法,其原理包含的内涵十分丰富,包含一些诸如列散度、拉普拉斯算子、梯度场、泊松方程等等数学知识,要完全弄明白确实需要一定的基础。这里就重点关注一下根据《Coordinates for Instant Image Cloning》(文献二)实现图像融合的过程,有机会的话再详细推导一下其原理。 21 | 22 | # 2. 实现 23 | ## 2.1. 准备 24 | 在OpenCV中,已经收录了泊松融合算法,也就是函数seamlessClone():
![seamlessClone][imglink1]
25 | 26 | 这个算法要求输入一个源图像,一个目标图像,源图像希望融合到目标图像的位置,以及一个mask图像。这个mask图像也就是一张二值化图像,用来标识图像的ROI(region of interest感兴趣区域)。均值坐标融合算法的输入参数也是一样的,不过mask图像很难以处理,OpenCV自带的GUI难以满足需求。所以我这里通过QT来做GUI,通过OpenCV将图像显示到QT窗体上,然后再QT窗体的图像区域内绘制多边形,多边形内部即为ROI。可以参考我的这两篇文章: 27 | [《使用QT显示OpenCV读取的图片》][netlink1] 28 | [《使用QT绘制一个多边形》][netlink2] 29 | 30 | ## 2.2. 核心 31 | ### 2.2.1. 均值坐标(Mean-Value Coordinates) 32 | 在论文中提出了一个很重要的概念也就是均值坐标(Mean-Value Coordinates)。对于如下多边形内部的点:
![Mean-Value Coordinates][imglink2]
33 | 34 | 都有一系列与多边形边界相关的坐标值:
![Mean-Value Coordinates][imglink3]
35 | 36 | 也就是说,只要确定了ROI,也就确定了ROI区域内每个点的均值坐标(Mean-Value Coordinates),每个点会有m个值(m为ROI边界多边形的顶点)。 37 | 38 | ### 2.2.2. ROI边界栅格化 39 | 论文中是以ROI边界多边形为例的,实际用到图像处理中是不会只用几个多边形的节点来计算的,而应该是ROI边界上连续的点。实际上不用想也知道,图像融合最关键的部分就是ROI边界部分的像素值。必须要用到ROI边界上所有的像素值来计算。 40 | 41 | 也就是说这里还需要一个工作,就是将ROI边界多边形栅格化,取得其上连续的像素位置,得到准确的栅格化多边形边界。这里可以参看我的这篇文章[《矢量线的一种栅格化算法》][netlink3]。按照顺序逐条将多边形的边栅格化,即可以得到ROI的栅格化多边形边界。 42 | 43 | ### 2.2.3. 核心实现 44 | 论文给出的算法伪代码如下:
![MCV融合][imglink4]
45 | 46 | 这段算法描述并不复杂,转换成自然语言如下: 47 | 1. 假设ROI区域内有n个点,其边界由m个点组成。 48 | 2. 那么可以求每个点的MVC(均值坐标),每个点有m个坐标值,一共有n个点,MVC就是就是一个n*m的矩阵。 49 | 3. 求ROI区域边界的像素差diff,显然其是一个m*1的矩阵。 50 | 4. 那么新图像ROI区域的插值为:r = MVC * diff,矩阵乘法后r为n*1矩阵。 51 | 5. 将插值r与原图像g矩阵相加:f = g + r,替换目标图像相应位置的值。 52 | 53 | 核心部分具体的实现代码如下: 54 | ```cpp 55 | QTime startTime = QTime::currentTime(); 56 | 57 | //Step1:找到边界上所有的像素点 58 | vector ROIBoundPointList; 59 | CalBoundPoint(ROIBoundPointList); 60 | 61 | //Step2:计算范围内每个点的 mean-value coordinates 62 | size_t srcImgBufNum = static_cast(srcImg.cols) * static_cast(srcImg.rows); 63 | vector> MVC(srcImgBufNum); 64 | for(size_t i = 0; i < srcImgBufNum; i++) 65 | { 66 | MVC[i].resize(ROIBoundPointList.size()-1, 0); 67 | } 68 | vector clipMap(srcImgBufNum, true); //标识范围内的点 69 | 70 | cout<<"开始计算 mean-value coordinates..." << endl; 71 | #pragma omp parallel for //开启OpenMP并行加速 72 | for (int ri = 0; ri < srcImg.rows; ++ri) 73 | { 74 | for (int ci = 0; ci < srcImg.cols; ++ci) 75 | { 76 | //点是否在多边形内 77 | size_t m = static_cast(srcImg.cols) * ri + ci; 78 | if(!Point_In_Polygon_2D(ci, ri, ROIBoundPointList)) 79 | { 80 | clipMap[m] = false; 81 | continue; 82 | } 83 | 84 | //逐点计算MVC 85 | Vector2d P(ci, ri); 86 | vector alphaAngle(ROIBoundPointList.size()); 87 | for(size_t pi = 1; pi < ROIBoundPointList.size(); pi++) 88 | { 89 | alphaAngle[pi] = threePointCalAngle(ROIBoundPointList[pi-1], P, ROIBoundPointList[pi]); 90 | } 91 | alphaAngle[0] = alphaAngle[ROIBoundPointList.size()-1]; 92 | 93 | 94 | for(size_t pi = 1; pi < ROIBoundPointList.size(); pi++) 95 | { 96 | double w_a = tan(alphaAngle[pi-1]/2) + tan(alphaAngle[pi]/2); 97 | double w_b = (ROIBoundPointList[pi-1] - P).Mod(); 98 | MVC[m][pi-1] = w_a / w_b; 99 | if(_isnan(MVC[m][pi-1])==1) 100 | { 101 | MVC[m][pi-1] = 0; 102 | } 103 | } 104 | 105 | double sum = 0; 106 | for(size_t pi = 0; pi < MVC[m].size(); pi++) 107 | { 108 | sum = sum + MVC[m][pi]; 109 | } 110 | 111 | for(size_t pi = 0; pi < MVC[m].size(); pi++) 112 | { 113 | MVC[m][pi] = MVC[m][pi] / sum; 114 | } 115 | } 116 | } 117 | cout<<"计算完成!" << endl; 118 | 119 | //Step3:计算边界的像素插值 120 | vector diff; 121 | for(size_t i = 0; i < ROIBoundPointList.size()-1; i++) 122 | { 123 | size_t l = (size_t) srcImg.cols * ROIBoundPointList[i].y + ROIBoundPointList[i].x; 124 | for(int bi = 0; bi < winBandNum; bi++) 125 | { 126 | size_t m = (size_t) dstImg.cols * winBandNum * (ROIBoundPointList[i].y + posY)+ winBandNum * (ROIBoundPointList[i].x + posX) + bi; 127 | size_t n = (size_t) srcImg.cols * winBandNum * ROIBoundPointList[i].y + winBandNum * ROIBoundPointList[i].x + bi; 128 | int d = (int)(dstImg.data[m]) - (int)(srcImg.data[n]); 129 | diff.push_back(d); 130 | } 131 | clipMap[l] = false; //在多边形边上的点没法计算MVC 132 | } 133 | 134 | //Step4:插值计算 135 | cout<<"开始插值计算..." << endl; 136 | //Mat rMat(srcImg.rows, srcImg.cols, CV_64FC3); 137 | #pragma omp parallel for 138 | for (int ri = 0; ri < srcImg.rows; ++ri) 139 | { 140 | for (int ci = 0; ci < srcImg.cols; ++ci) 141 | { 142 | size_t l = (size_t) srcImg.cols * ri + ci; 143 | if(!clipMap[l]) 144 | { 145 | continue; 146 | } 147 | 148 | vector r(winBandNum, 0); 149 | 150 | for(size_t pi = 0; pi < MVC[l].size(); pi++) 151 | { 152 | for(int bi = 0; bi < winBandNum; bi++) 153 | { 154 | r[bi] = r[bi] + MVC[l][pi] * diff[pi * winBandNum + bi]; 155 | } 156 | } 157 | 158 | for(int bi = 0; bi < winBandNum; bi++) 159 | { 160 | size_t n = (size_t) srcImg.cols * winBandNum * ri + winBandNum * ci + bi; 161 | size_t m = (size_t) dstImg.cols * winBandNum * (ri + posY)+ winBandNum * (ci + posX) + bi; 162 | 163 | dstImg.data[m] = min(max(srcImg.data[n] + r[bi], 0.0), 255.0); 164 | } 165 | } 166 | } 167 | cout<<"插值完成!" << endl; 168 | 169 | QTime stopTime = QTime::currentTime(); 170 | int elapsed = startTime.msecsTo(stopTime); 171 | cout<<"总结完成用时"<![MCV融合][imglink5] 181 | 182 | 点击"绘制"按钮,在源图像区域内绘制一个多边形,确定一个ROI:
![MCV融合][imglink6]
183 | 184 | 准备一张想要融合的目标图像:
![MCV融合][imglink7]
185 | 186 | 点击"融合"按钮,会加载目标图像,并会根据设置的位置,将源图像的ROI融合到目标图像中:
![MCV融合][imglink8]
187 | 188 | ## 3.2. 效率 189 | 在Debug模式,不使用OpenMP加速的情况下,这个算法的效率大约需要50秒左右的时间。 190 | 191 | 在Debug模式,使用OpenMP加速,算法的效率可以优化到10秒,也就是不使用OpenMP加速时的5倍左右。而我使用的机器CPU是i7-8750H标压6核CPU,考虑到一些IO操作造成的性能损耗,这个优化效率是正常的。 192 | 193 | 最后在使用Release模式,使用OpenMP加速之后,算法的效率可以优化到1秒左右,这说明编译器优化对程序性能也是有很大影响的,尤其是对并行程序而言。 194 | 195 | 这个实现只是这个算法的初始实现,效率就已经达到了1秒左右,看来论文说的可以达到实时融合确实不是虚言。有机会再尝试一下论文中提到的一些性能优化实现。 196 | 197 | # 4. 参考 198 | [1] [泊松融合及其优化算法](https://zhuanlan.zhihu.com/p/31680396) 199 | 200 | [2] [Coordinates for Instant Image Cloning](https://www.cse.huji.ac.il/~danix/mvclone/) 201 | 202 | [3] [图像处理(十二)图像融合(1)Seamless cloning泊松克隆-Siggraph 2004](https://blog.csdn.net/hjimce/article/details/45716603) 203 | 204 | [4] [多尺度并行坐标插值实时图像克隆算法](http://sjcj.nuaa.edu.cn/sjcjycl/article/html/201901014) 205 | 206 | [实现代码](https://github.com/fafa1899/MVCImageBlend) 207 | 208 | [基于均值坐标(Mean-Value Coordinates)的图像融合算法的优化实现](https://blog.csdn.net/charlee44/article/details/104979382) 209 | 210 | [netlink1]:https://blog.csdn.net/charlee44/article/details/104464262 211 | [netlink2]:https://blog.csdn.net/charlee44/article/details/104696765 212 | [netlink3]:https://blog.csdn.net/charlee44/article/details/104662373 213 | 214 | [imglink1]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/1.PNG 215 | [imglink2]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/2.PNG 216 | [imglink3]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/3.PNG 217 | [imglink4]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/4.PNG 218 | [imglink5]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/5.PNG 219 | [imglink6]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/6.PNG 220 | [imglink7]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/7.jpg 221 | [imglink8]:https://raw.githubusercontent.com/fafa1899/MVCImageBlend/master/README_IMG/8.PNG -------------------------------------------------------------------------------- /README_IMG/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/1.PNG -------------------------------------------------------------------------------- /README_IMG/2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/2.PNG -------------------------------------------------------------------------------- /README_IMG/3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/3.PNG -------------------------------------------------------------------------------- /README_IMG/4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/4.PNG -------------------------------------------------------------------------------- /README_IMG/5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/5.PNG -------------------------------------------------------------------------------- /README_IMG/6.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/6.PNG -------------------------------------------------------------------------------- /README_IMG/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/7.jpg -------------------------------------------------------------------------------- /README_IMG/8.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/README_IMG/8.PNG -------------------------------------------------------------------------------- /data/source.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/data/source.jpg -------------------------------------------------------------------------------- /data/target.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/data/target.jpg -------------------------------------------------------------------------------- /mvc-final-opt.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/mvc-final-opt.pdf -------------------------------------------------------------------------------- /论文翻译.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fafa1899/MVCImageBlend/fcea9e25c2805e6bd1f40bfc37ea56079479e3d4/论文翻译.doc --------------------------------------------------------------------------------