请看赵春江https://me.csdn.net/zhaocj的主页,他已经对Opencv图像拼接流程中的代码做了很详细的解释。前人栽树,后人乘凉。

一.本文所做的事

1.重构了Opencv图像拼接的源代码,整个代码是面向过程的;

2.在赵春江源码分析基础上,对一些细节部分进行说明。

代码链接:https://github.com/mhhai/ImageStitch

二.特征点检测

一切起源于这段代码

Ptr

finder =newOrbFeaturesFinder(); 这段代码生成了一个OrbFeaturesFinder对象,其构造函数为:

OrbFeaturesFinder

可以看出这里面创建了一个ORB类。关于这一点,看OrbFeaturesFinder类的继承结构

真正实现ORB算法是在orb.cpp中的ORB_Impl类,其他的都是一些函数调用过程,这也是opencv难以看懂的部分。OrbFeaturesFinder类声明(在matchers.hpp)如下:

class 

可以看出OrbFeaturesFinder是没有重载()的,那么它为什么可以使用

(

这段代码呢,因为在其父类FeaturesFinder中实现了()的重载,派生类直接使用父类的公有方法。父类FeaturesFinder重载()代码如下:

void 

接下来,在函数operator()中,调用了find函数,由于OrbFeaturesFinder类实现了自己的find函数版本,所以,接下来执行OrbFeaturesFinder中的find函数,该函数有点长,但还是拿来说明一下:

void 

之所以把这段这么长的代码贴出来,是因为这段代码从全局的角度讲述了怎样进行特征点检测。继续看

finder = new  OrbFeaturesFinder();

这段代码,由OrbFeaturesFinder类的构造函数可知,使用默认参数时是检测出1500个特征点,建立5层高斯金字塔图像,那么第一个参数Size(3,1)参数作何解释?Size(3,1)是说把图像分成1 * 3的网格,对每个网格进行特征点检测,每个网格检测出的数目是500,那么总共检测出的特征点数目就为1500,可以看下面的示意图:

不是检测出1500个特征点吗,在哪里设置500这个参数了?其实在你第一次写

finder = new  OrbFeaturesFinder();

这段代码时,构造函数中的这段代码

orb = ORB::create(n_features * (99 + grid_size.area())/100/grid_size.area(), scaleFactor, nlevels);

create函数第一个参数的值被设置成了510,也就是每个区域检测出的特征点数目不是刚好500,而是多一点。通过设置find的函数中的r、c参数,你可以对想要的部分进行特征点检测。另外,从这里可以看出,Opencv实现的ORB特征点检测并不是对整幅图像建立高斯金字塔,而是对每个网格建立高斯金字塔。另外每层金字塔检测出来的数目是根据尺度实现分配好的,这方面可以参看赵春江的书或者博客。

三.特征点匹配

这一部分类与类之间的关系比较复杂,具体可以看下图:

特征匹配使用的是最近邻匹配(BestOf2NearestMatcher),实现最近邻匹配可以使用暴力匹配法和K-D树最近邻搜索。不是说暴力匹配法一定不好。对于3000个特征点对以下的特征匹配,暴力匹配法是优于K-D树搜寻的,因为K-D树的构建本身就需要耗费时间。

当你使用下面代码时

BestOf2NearestMatcher 

其构造函数为:

BestOf2NearestMatcher

该类内部维护的一个FeaturesMatcher对象(智能指针)就被实例化为CpuMatcher,所以特征匹配调用的关系虽然很复杂,但是没有必要去研究这些,只需要着重于CpuMatcher类中的match函数,该函数实现了两个特征点集之间的匹配。BestOf2NearestMatcher类也有一个match函数,该match函数属于更上层,它调用了CpuMatcher类中的match()函数以及findHomography()函数,其中findHomography()实现了使用RANSAC算法去除误匹配。关于findHomography()重构的代码放在下一小节中,findHomography()能够看到RANSAC算法的精细之处。另外,knnMatch()代码没有重构出来,个人感觉这部分代码重构难度大,而且不重要,因此还是重构findHomography()更具有意义。

四.计算单应性矩阵

这部分代码是在特征匹配的基础上继续深入的,目的是为了更好地看出计算单应性矩阵的过程。包括通过4个点计算单应性矩阵、使用重映射误差剔除外点,更新RANSAC算法的迭代阈值等。

五.恢复相机内外参

这部分代码只重构的相机内参的部分。相机外参涉及到光束平差法、雅可比矩阵和波形校正等等。。。这部分我也很晕。所以,计算外参,尤其是多幅图像拼接之间的外参计算是很麻烦的。愿有后来人能将这部分代码讲清楚。。。

六.投影变换

如果你的项目镜头是固定的,也就是说你的内外参是固定的,上面的结果就可以看作是预训练的过程。因此你就可以不需要太去了解光束平差法怎么实现之类的细节问题。这一部分我会再细讲一下。

七.动态规划法寻找最佳缝合线

这部分很早之前就重构出来了,因此很多细节都我忘了。还是可以看一看的。

八.图像融合

这部分是我针对项目中特殊镜头成像写的,因此不具普遍性。这部分代码主要包括计算能量函数、寻找最佳缝合线,渐入渐出法融合。因为只寻找了小部分的缝合线,所以PC机图像融合部分耗是0.3s(两张图片)。当然还是很慢。由于Opencv羽化融合不适合我的图像,所以前面代码中的pano结果中间会有细微的黑影。

总结:

基本重构出了Opencv图像拼接整个流程的代码,由于一些工作是早期做的,所以很多东西没有记录下来,只有重构好的代码保留了下来。所以大家可以当作这是一份参考资料。

c++ opencv mat_图像拼接Opencv源码重构相关推荐

  1. 基于OpenCV&ORB和特征匹配的双视频图像拼接(源码&部署教程)

    1.双视频拼接效果展示 2.视频演示 [项目分享]Python基于OpenCV&ORB和特征匹配的双视频图像拼接(源码&部署教程)_哔哩哔哩_bilibili 3.背景 随着汽车电子和 ...

  2. Python基于OpenCV&ORB和特征匹配的双视频图像拼接(源码&部署教程)

    1.双视频拼接效果展示 2.视频演示 [项目分享]Python基于OpenCV&ORB和特征匹配的双视频图像拼接(源码&部署教程)_哔哩哔哩_bilibili 3.背景 随着汽车电子和 ...

  3. c++ opencv mat_实战 | OpenCV 实现多张图像拼接

    点击上方"计算机视觉life",选择"星标" 快速获得最新干货 本文转载自OpenCV学堂,主要介绍图像拼接Stitch模块算法流程与代码使用介绍 拼接算法 O ...

  4. 【OpenCV流程+代码分析】Opencv HOG行人检测 源码分析

    [原文:http://blog.csdn.net/ttransposition/article/details/11874285] OpenCV demo演示见本人的另一篇灌水博客 http://bl ...

  5. 在Ubuntu上编译opencv 2.4.13源码支持android平台操作步骤

    之前在https://blog.csdn.net/fengbingchun/article/details/96430706中编译过opencv源码用于海思平台,这里通过修改脚本编译opencv 2. ...

  6. C/C++实现双目矫正(不使用OpenCV内部函数)及矫正源码解析

    C/CPP实现双目矫正(不使用OpenCV)及矫正源码解析 这篇文章是之前[要matlab标定数据做双目相机矫正OpenCV C++]的补充,再加上了双目矫正的原理及代码注释.更新中-- 本文所需数据 ...

  7. opencv + contrib windows下源码编译

    网上,包括书上有很多人云亦云的源码编译方式,不能说不正确但是有很多弯弯绕绕(坑).最近刚做完了一个识别项目的第一个版本,总结了一下..为了写这篇文章,特意重新在自己电脑搭了一遍开发环境. 最权威的方式 ...

  8. OpenCV下载安装与源码调试。

    1.下载CMake(不编译源码可以直接跳过CMake相关说明):安装最新版本即可. 官网:https://cmake.org/download/ github:https://github.com/o ...

  9. OpenCV人脸检测(完整源码+思路)

    本博文IDE为vs2013 OpenCV2.49 话不多说,先看视频演示(20S演示): 如下: https://v.youku.com/v_show/id_XMjYzMzkxMTYyMA==.htm ...

最新文章

  1. [UVALive 3177] Beijing Guards
  2. linux 复制栈数据结构,算法-数据结构-堆栈
  3. PHP多种形式发送邮件
  4. java日期用什么属性_java日期以及使用Java反射机制遍历实体类的属性和类型
  5. java 数据库 事务 只读_不使用事务和使用只读事务的区别
  6. mysql 停数据库_mysql数据库突然停了
  7. php zscan,PHP redis SCAN、SSCAN、ZSCAN、HSCAN 的使用, pipe 快速redis插入数据
  8. python cnn 实例_Python实现CNN的多通道输入实例
  9. suse linux快捷键,Suse Linux整理大全:快捷键
  10. 冀教版小学三年级上册计算机教案,冀教版小学三年级上册信息技术教案三篇
  11. 编写一个图片去水印的小工具
  12. 通过xshell命令方式下载文件
  13. 【STM32】R05D电控红外协议的美的空调遥控器
  14. 优达twitter 清理_优达资源 | 12个数据可视化工具,人人都能做出超炫图表
  15. 2020进阶版 -【C语言/C++编程语言学习路径图】!
  16. python局域网聊天
  17. yolo v5 数据标注和训练
  18. Android中将byte大小转换为KB、MB、GB等
  19. android 7 文件恢复,手机文件恢复APP
  20. 算法与数据结构(一):线性表(C++实现)

热门文章

  1. DBGridEh全部属性设置详解
  2. linux服务sendmail邮件服务
  3. MSSQLServer基础07(事务,存储过程,分页的存储过程,触发器)
  4. 《Head First 设计模式》阅读笔记(一)——策略模式
  5. SQLSERVER 创建ODBC 报错的解决办法 SQLState:‘01000‘的解决方案
  6. SIGIR 2020 | 知识图谱上推荐推理的模仿学习框架
  7. 【报告分享】汽车行业“无接触”营销风险初探.pdf(附下载链接)
  8. 【报告分享】2019抖音创作者生态报告.pdf
  9. 算法工程师面试备战笔记4_余弦相似与欧氏距离有什么区别和联系
  10. 剑指offer 面试题59 - II. 队列的最大值