添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
阳光的警车  ·  antd ...·  11 月前    · 
内向的炒面  ·  php latin1转成utf-8,PHP ...·  1 年前    · 
虚心的长颈鹿  ·  ILRuntime 学习 - void87 ...·  1 年前    · 

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

一.本文所做的事

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

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

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

二.特征点检测

一切起源于这段代码

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

OrbFeaturesFinder

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

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

class 

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

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

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

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

finder = new  OrbFeaturesFinder();

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

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

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

请看赵春江https://me.csdn.net/zhaocj的主页,他已经对Opencv图像拼接流程中的代码做了很详细的解释。前人栽树,后人乘凉。一.本文所做的事1.重构了Opencv图像拼接的源代码,整个代码是面向过程的;2.在赵春江源码分析基础上,对一些细节部分进行说明。代码链接:https://github.com/mhhai/ImageStitch二.特征点检测一切起源于这段代码Ptrf...
opencv 自带的stitching速度很慢, 其中一个最大的原因是每一张图都要和其它的图去匹配,如果有10张图,除去自身不用匹配外,要匹配 10X(10-1) = 90 次。10张532*300图拼接耗时14s左右,还姑且能忍受。可是100张图要匹配9900次。耗时不是简单的线性增长。 Stitch读入图像不用按照从左到右的顺序,拼接结果和运行时间都是一样的。 我们拍摄全景图的时候都是从左到右,...
Written by Paul Bourke EEG data courtesy of Dr Per Line December 1996, Updated December 1999 立体效果(在2维平面
很多情况下,使用一个全局单应变换并不能准确对齐图像,需要一些后处理来削弱拼接的痕迹,比如寻找 最佳 拼接缝。使用全局单应变换的对齐结果,实现代码参考 图像拼接 (六): OpenCV 单应变换模型拼接两幅图像:仔细观察,在拼缝的下方出现了没对齐的问题。寻找 最佳 拼接缝算法中,Graph Cut很经典。它将计算机视觉问题和网络流联系在一起。寻找 最佳 拼接缝等价于求网络流的最小割。 在网络流问题中,最小割和最大流相等
1. 仿射变换 在仿射变换中,原图中所有的平行线在结果图像中同样平行。首先在原图像中找到3个点以及它们在输出图像中对应位置,然后cv2.getAffineTransform会构造一个2x3矩阵,最后这个矩阵会被传给函数cv2.warpAffine。如下所示: import cv2 import numpy as np from mat plotlib import pyplot as plt
你好,关于 opencv 全景 图像拼接 的代码,我可以为您提供一些参考。首先,您需要使用 opencv 库中的stitching模块,该模块提供了全景 图像拼接 的功能。具体的代码实现可以参考以下步骤: 1. 加载图像:使用 opencv 中的imread函数加载需要拼接的图像。 2. 特征提取:使用 opencv 中的ORB、SIFT等算法提取图像的特征点。 3. 特征匹配:使用 opencv 中的BF Mat cher、FlannBased Mat cher等算法进行特征点的匹配。 4. 图像配准:使用 opencv 中的findHomography函数计算图像的变换矩阵。 5. 图像拼接 :使用 opencv 中的warpPerspective函数将图像进行拼接。 以上是大致的步骤,具体的代码实现可以参考 opencv 官方文档中的示例代码。希望能对您有所帮助。