HartSift: 一种基于GPU的高准确性和实时SIFT

HartSift: 一种基于GPU的高准确性和实时SIFT,第1张

尺度不变特征变换 (SIFT) 是最流行和最强大的特征提取算法之一,因为它对尺度、旋转和光照保持不变。它已被广泛应用于视频跟踪、图像拼接、同时定位和映射(SLAM)、运动结构(SFM)等领域。然而,高计算复杂度限制了其在实时系统中的进一步应用。这些系统必须在准确性和性能之间进行权衡以实现实时特征提取。他们采用其他更快但精度较低的算法,如 SURF 和 PCA-SIFT。为了解决这个问题,本文提出了一种使用 CUDA 的 GPU 加速 SIFT,命名为 HartSift,充分利用单机CPU和GPU的计算资源,实现高精度、实时的特征提取。实验表明,在 NIVDIA GTX TITAN Black GPU 上,HartSift 可以根据图像的大小在 314-1057ms (9461-31847fps) 内处理图像。此外,HartSift 分别比 OpenCV-SIFT(CPU 版本)和 SiftGPU(GPU 版本)快 5934-7596 倍和 401-649 倍。同时,HartSift 的性能和 CudaSIFT(迄今为止最快的 GPU 版本)的性能几乎相同,而 HartSift 的准确度远高于 CudaSIFT。

SIFT算法可以提取大量显著特征,这些特征在缩放、旋转、光照和3D视点保持不变,还提供了跨越噪声和仿射失真的稳健匹配。但SIFT的高计算复杂度限制了其在大规模数据和实时系统中的进一步应用。而复杂度较低的算法,如SURF、PCA-SIFT的准确性又不太高。因此,在主流计算平台上实现高精度、实时的SIFT是一个重要而有意义的研究课题。

而SIFT算法具有很好的并行性,可以正确移植到GPU上。因此,在配备GPU的异构计算系统上实现高性能的SIFT具有重要的实用价值。

SIFT 算法包含三个阶段,包括高斯差分(DoG)金字塔的构建、精确的关键点定位和 128 维描述符生成。由于每个阶段都有自己的并行特性,因此必须使用不同的并行粒度和优化来实现高性能。尤其是后两个阶段,负载不平衡不利于GPU优化,会导致性能下降。

本文的主要贡献和创新可以概括如下:

有许多工作尝试在GPU上使用SIFT算法。

然而,为了实现高性能,他们省略了 SIFT 算法的一些重要步骤,例如将输入图像加倍、保持尺度变化的连续性和拟合二次函数以定位准确的关键点信息。作者的实验表明,这些遗漏会导致 SIFT 丢失很多关键点和准确性。

Lowe将输入图像尺寸加倍作为高斯金字塔 的最底层,每个尺度 通过高斯卷积产生:

高斯金字塔确定之后,利用相同Octave的层级相减,得到差分金字塔:

其中 ,在本文中,

检测尺度空间极值

将DoG金字塔每个像素与相邻像素比较,同层8个,上下层9个,若像素是局部最大值或局部最小值,将其视为关键点候选。

去除无效关键点

去除较低对比度和不稳定边缘响应的候选关键点,通过将3D二次函数拟合到附近数据执行子像素插值,以获取精确的位置、比例和主曲率比。

方向分配

将候选关键点周围的梯度累积到36 bins的直方图中,根据每层的尺度计算搜索半径。每个紧邻像素由一个高斯加权窗口加权,梯度方向累计到36 bins的方向直方图中。峰值为主要梯度方向,同时超过峰值80%的局部峰值bin也被视为关键点方向。

对关键点周围像素计算梯度直方图,搜索半径比上一步骤大得多,同样用一个高斯加权函数用于为每个邻居的梯度值分配权重。

根据梯度方向将最终的梯度值累积到一个 360-bin 的圆形方向直方图。最后,直方图将被归一化、平滑并转换为 128D 描述符。

构建金字塔应该保持顺序,以保证尺度空间变化连续性。Acharya和Bjorkman为加快这一过程,牺牲准确性打破构建顺序。考虑到不能使准确性降低,构建顺序在HartSift中保留。

分离卷积核

对于 大小的卷积核处理 大小的图像需要进行 次运算,如果将2D卷积核拆解为两个1D的卷积核,计算量减少至 通过使用共享内存和向量化方法,更容易实现合并全局内存访问并减少一维卷积的冗余访问。

Uber 内核

Uber内核将多个不同任务放到一个物理内核中,在一个内核中并行处理任务,而不需要在内核之间切换。差分金字塔第 层由高斯金字塔第 和第 层决定。将高斯差分金字塔和高斯卷积核封装在单个核中,可以充分挖掘并行性。

线程不需要重复读取高斯金字塔第 层的值,这是由于第 层的值计算完后,结果会放在寄存器内而不是全局内存中。借助Uber内核的优势,我们可以节省 的空间和 的内核运行时间

异构并行

HartSift 采用异构并行方法来加速这一阶段。CPU 和 GPU 将并行协作,构建 DoG 金字塔。

由于GPU处理小图像没有优势,作者将 以下的图像放到CPU处理,大图像放到GPU处理。用户也可以自行设置分离点,确保CPU和GPU负载平衡。

存在两个问题:

负载均衡

Warp是GPU最小并行执行单元,即以锁步方式执行的 32 个线程的集合。若负载不均衡,则warp执行时间取决于最后一个线程完成的时间,warp负载不均衡会导致GPU效率降低。

由于候选关键点分布的随机性,几乎所有经线都包含不同数量的空闲线程。如果这些warp继续处理以下部分,就会出现两个级别的负载不平衡

在去除无效的候选关键点部分时,线程将进行亚像素插值以获得准确的候选关键点信息,从而去除具有低对比度或不稳定边缘响应的关键点候选。换句话说,一些线程会比其他线程更早返回一次。负载不平衡会变得更加严重。

为了突破性能瓶颈,HartSift 引入了重新平衡工作负载和多粒度并行优化。

重新平衡工作负载

当检测到负载不平衡时,HartSift 将通过启动具有适当粒度的新内核并分派每个具有 32 个活动线程的新经线来重新平衡工作负载。

此外,启动三个内核分别处理这三个部分,不仅可以重新平衡工作量,还可以根据不同部分的并行特性提供多粒度的并行。

多粒度并行

重新平衡工作负载优化保证每个内核中的线程和经线被完全加载,多粒度并行优化保证工作负载将平均分配到线程和经线。此外,不同内核的并行粒度取决于工作负载的特性。

HartSift通过将一个线程映射到一个或多个像素,采用与关键点候选检测部分和无效关键点去除部分并行的线程粒度。然而,线程粒度并行会导致方向分配部分的负载不平衡,因为不同关键点的相邻区域半径不同。线程粒度并行会为单个线程分配过多的工作,这在某些情况下限制了硬件资源的利用率。所以在这部分应用混合粒度并行:扭曲粒度构建直方图,线程粒度找出并将主导方向分配给相应的关键点。

基于扭曲的直方图算法

作者针对每个关键点提出了一种基于扭曲粒度和原子 *** 作的高性能直方图算法,以充分利用局部性。

该阶段关键点的邻域半径远大于前一阶段。需要为每个关键点累积数千个邻居到一个 360-bin 直方图。如果采用前一阶段的基于原子扭曲的直方图算法,会对这一阶段的性能产生不同的影响。

HartSift引入了一种atomic-free的直方图算法,进一步提升了这一阶段的性能。

该算法包含三个步骤:

为了消除线程间的负载不平衡,实现全局合并访问,HartSift 使用一个warp 来处理一个keypoint 的所有邻居。当线程计算出它们的方向 bin 时,它们需要根据bin变量的值将梯度值累加到局部直方图。考虑到有如此多的邻居并且一个经线的一些线程可能具有相同的 bin,算法1引入了一种无原子的多键约简方法来累积每个经线的部分和。这种方法可以利用warp级shuffle和vote指令完全消除原子 *** 作和本地同步。它根据bin对经纱的线程进行分组并指定每组具有最低车道的线程作为队长线程。队长线程将保存他们自己的 bin 的部分总和,并将它们并行地累积到驻留在共享内存中的本地直方图,而不会发生 bank 冲突和同步。在遍历所有邻居后,HartSift 将最终的局部直方图复制到驻留在全局内存中的全局直方图。

本文提出了一种GPU上的并行SIFT,命名为Hart-Sift,它可以在单机内同时使用CPU和GPU来实现高精度和实时的特征提取。HartSift根据每个阶段的不同特点,通过适当采用不同的优化策略来提升性能,例如负载均衡、基于warp的直方图算法和不同尺度样本的atomic-free直方图算法等。在NVIDIA GTX TITAN Black GPU上,HartSift可以在314 ~ 1057ms(9461 ~ 31847fps)内提取高精度特征,轻松满足高精度和实时性的苛刻要求。另外,与OpenCV-SIFT和SiftGPU相比,HartSift获得了5934 ~ 7596倍和401 ~ 649倍加速分别。同时,HartSift 和 CudaSIFT 的性能几乎相同,但 HartSift 远比 CudaSIFT 准确。

基于不变量技术的特征检测方法的基础上,提出的一种基于尺度空间的、对图像缩放、旋转、仿射变换、光照变化保持稳定性的图像局部特征描述算法-SIFT算子。SIFT特征点向量的生成由以下四步骤组成:1、在尺度空间中检测极值点;2、去除低对比度的极值点和不稳定的边缘极值点,得到特征点;3、计算特征点的方向参数;4、生成SIFT特征点向量,向量维数一般为128维。运用SIFT算法提取的SIFT特征点向量具有如下优点:1、SIFT特征是图像的局部特征,对旋转、尺度缩放、亮度变化保持不变化性,对视角变化、仿射变换、噪音也保持一定程度的稳定性;2、独特性好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配;3、多量性,即使少数的几个物体也可以产生大量SIFT特征向量。现有的SIFT算法具有一定的缺陷,对于图像的检测效率和检测精度较差。

技术实现思路

有鉴于此,本专利技术实施例的目的在于提供一种基于改进SIFT的图像特征检测方法及装置,以解决上述技术问题。第一方面,本专利技术实施例提供了一种基于改进S

技术保护点

1一种基于改进SIFT的图像特征检测方法,其特征在于,包括:获取待检测图像和对应的标准图像;利用尺度不变特征变换SIFT算法对所述待检测图像和所述标准图像进行图像匹配,获得多对匹配点;计算所述匹配点之间的邻域直径比和方向角度差;根据所述邻域直径比和所述方向角度差对所述匹配点进行剔除,获得正确匹配点,以获得所述待检测图像中的特征。

Viola-jones人脸检测算法是一种基于滑动窗口的目标检测算法,但它却克服了滑动窗口检测带来的低效问题,可以用于实时人脸检测,主要归功于以下三点:

我参考论文[1]实现了Viola Jones中提到的attention cascade检测框架,此处是 github传送门 。

下面进一步详细介绍整个检测原理。

基于滑窗的目标检测基本原理很简单,首先构建一个classifier(分类器),以人脸检测为例,分类器的工作是判断给定大小的图像的是否为人脸,用该分类器从左至右从上到下扫描整幅图像,扫描获取的部分图像称为子窗(文章中子窗大小为24x24像素),当分类器判断子窗是人脸时,即完成了人脸检测。

这样处理有个问题,如果图像中包含的人脸变大了,此时采用固定大小的子窗就无法进行检测。通常有两种解决方法,1 采用image-pyramid(图像金字塔),也就是通过resize获得多种不同大小图像并堆叠在一起,用固定大小分类器同时对所有图像进行扫描;2 采用不同大小的分类器进行扫描。文章中用到的是第二种方法,尽管如此,虽然避免了调整图像大小带来的计算开销,但不同大小的分类器意味着有更多子窗需要进行处理。

如何构建一个足够快的分类器来对每个子窗进行快速判断。

分类器的构建有两种方式,一种是pixel-based(基于像素),另一种是feature-based(基于特征)。当把神经网络作为图像分类器时,输入是图像的像素值,即基于像素的分类器。用图像像素作为输入不包含任何和待分类目标有关的特定信息,往往训练这种分类器需要大量数据,并且分类过程较慢。基于特征的分类器就是先针对图像进行特征提取(HOG特征,SIFT特征等),再利用获取的特征进行分类。这种分类器不需要大量训练数据,且计算量一般会在特征计算部分,相对较小。

文章采用的是基于特征的分类器,选取了一种较为简单的特征即haar-like特征。利用矩形个数对可以将haar-like特征分为三类,分别由两个,三个,和四个 大小相同 的矩形组成。全部列举出来可以分为以下(a)(b)(c)(d)(e)五类(注意是五类不是五个,具体有多少个haar-like特征是由子窗大小决定的)。如下图所示(文章[1]中的图)。

当子窗大小给定后,我们可以用五个参数唯一确定 一个 haar-like特征,即特征种类(a/b/c/d/e),左上角x轴坐标,左上角y轴坐标,矩形的长,矩形的宽。对应的特征值等于位于白色矩形框中像素值总和减去位于黑色矩形框中的像素值总和。文章中用到的子窗大小为24x24像素,可以计算出来总共有162336个特征(把在子窗中所有可能位置和可能大小的特征全部列举出来)。利用haar-like特征进行分类只需两步:

haar-like特征有两个优点,第一是它是scale-invariant(不随大小而改变)的,第二是可以通过积分图像快速计算。简单的说下第一点的含义,例如我们用24x24像素的训练样本训练获取一组haar-like特征和对应的门限值,当对图像进行扫描时,子窗大小调整为SxS像素,此时只需将特征中的矩形大小按同样比例进行缩放(门限值同样需要缩放),计算所得的特征值依然是有效的。

积分图像是受卷积的微分性质启发而定义一种数据结构。积分图像定义:

其中 为积分图像, 为原图像。积分图像中 位置处的像素值等于原图中位于 的左侧和上方的所有像素值之和。有了积分图像我们就可以快速计算haar-like特征,以特征(a)为例,如下图所示。

S1到S6是积分图像在这六个顶点上的值。该特征值等于位于A中的像素总和减去位于B中的像素总和,而A中像素总和等于S5+S1-S2-S4,B中像素总和等于S6+S2-S3-S5,并且无论矩形多大,我们总能在固定时间内计算出特征值(6次索引 *** 作和少量的加法乘法计算)。积分图像只需计算一次后续可以一直使用,事实上在算法实现时,我们只需保存样本的积分图像,原图像反而不用保存。

现在找到了一类特征用于构建分类器,和快速计算该类特征的方法。分类器是由一组特征构成的,而不是一个,如何找到一组有效的特征。

文章列举了前人的一些特征选取方法(此处就不列举了),它们虽然取得了一定的效果,但最终选出来的特征数量还是太多。文章将adaBoost算法用于特征选取(创新点),即每次训练的弱分类器的过程看做特征选取的过程,一次从162336个特征中选取一个特征(同时还包括了对应的门限值,极性,加权误差)。

adaboost算法就不详细介绍了,它的基本思想是训练一系列“弱”分类器,组成一个committee(即每个弱分类器都有投票权,但是权重不同,加权误差越小的弱分类器权重越大)。adaboost采用迭代训练方式,给定一个t阶committee,如何寻找第t+1个弱分类器和对应的权重,以最小化在一定分布下的训练样本的加权指数损失。这个优化过程可以转换为对训练样本的分布进行调整(即增大上一轮错误判断的样本的权重,减小正确判断的样本权重),在调整后的样本分布下寻找最小化加权0-1损失的弱分类器并计算对应的加权0-1损失。

可以利用adaboost找到一组特征构成分类器,使得该分类器有极高的准确率和召回率(这种分类器势必会有较大的计算量),这样会导致图像中的每一个子窗都享有同等的计算量,扫描一整幅图会有几十万甚至上百万子窗,总体计算量依然很大。实际上一幅图像中只有极少可能包含人脸的位置是我们感兴趣的,其他不包含人脸的子窗我们希望能够快速筛除,将更精细的计算用于包含人脸的子窗。

文章引入了attention-cascade的机制(注意力级联),即训练多个分类器进行级联,替代单一的分类器。结构如下图所示(文章[3]中的图)。

上图所示的分类器有三级,上一级的输出是下一级的输入,只有预测为正的样本才能传递给下一级,预测为负的样本直接舍弃。大部分非人脸子窗往往在前几级分类器就被舍弃,这样使得扫描每个子窗所需的平均计算量大大减小。

分类器是一级一级训练之后级联起来的,训练分类器时,整个级联分类器的假负率(fpr_overall)有一个训练目标(文章[1]中设置为10e-7),同时每一级有一对训练目标,即假正率和假负率。每级分类器训练的思想是在假负率极低的情况下(文章[1]中设置为0005)尽量得到一个较低的假正率(文章中[1]中设置为05),即我们保证在正样本尽可能多的通过该级分类器的情况下尽量筛除更多的负样本。文章[3]通过一个松弛量来调节假正率和假负率。

下一级用到的训练数据是由所有的正样本和上一级输出的假正样本组成的,这样训练的好处是可以让处于级联后半部分的分类器“看到”更多负样本数据,缺点是训练后期假正样本很难获取,训练时间会比较长。

尽管我们获取了一个级联分类器,但依然不能保证对同一幅图中的一张人脸只会检测到一次(子窗相对人脸有所便宜或者缩放子窗大小都可能导致重复检测),如何消除重复检测,获得更好的检测效果。

文章[3]中说的较为简略,主要是针对检测框构建并查集,并对并查集中的候选框求平均得出最终的检测框。

文章[1]中是采用连通分量算法,计算每种大小检测框的置信度,根据置信度选取最终结果,但前提是检测器在图像中扫描的步进必须是1个像素,处理时间可能会比较长。

只能用于正脸检测,如果人脸朝屏幕内外或者在屏幕平面上旋转均有可能失效

在背景较亮,人脸较暗的情况下可能失效。

在有遮挡的情况下大概率失效。

OpenMVG (open Multiple View Geometry):开源多视角立体几何库,这是一个cv届处理多视角立体几何的著名开源库,信奉逗简单,可维护地,提供了一套强大的接口,每个模块都被测试过,尽力提供一致可靠的体验。

地址:github

文档:documents

openMVG能够:

解决多视角立体几何的精准匹配问题;

提供一系列SfM需要用到的特征提取和匹配方法;

完整的SfM工具链(校正,参估,重建,表面处理等);

openMVG尽力提供可读性性强的代码,方便开发者二次开发,核心功能是尽量精简的,所以你可能需要其它库来完善你的系统。openMVG分成了几个大的模块:

核心库:各个功能的核心算法实现;

样例:教你怎么用;

工具链:也就是连起来用咯(乱序图像集的特征匹配,SfM,处理色彩和纹理);

#0 安装(win10+VS2013)

第一步当然是从github clone代码,然后按照 BUILD 说明 *** 作,需要注意的是:

template <class T> inline T operator|(T x, T y){

return static_cast<T>(static_cast<int>(x) | static_cast<int>(y));

};

建议和opencv一起编译,方法是在CMakeListstxt文件中修改相应选项为 ON,然后在cmake的GUI中添加一个叫OpenCV_DIR的入口,值就是你已经安装好的opencv的路径。

openMVG写的非常不错,对Windows也提供了良好的支持,所以cmake之后用VS打开生成的openMVGsln解决方案就可以进行编译了,编译的时间稍久。我用的VS2013不支持C++新特性:constexpr,所以建议你使用VS2015或更新版本,如果一定要用VS2013,可以这样做:在src/openMVG/cameras/Camera_Commonhpp文件中将有constexpr的地方直接去掉,或者改成模板函数也是可以的:

运行样例,这里遇到一个坑:DenseStoraageh line 86报错:R6010 Assertion failed,这是一个断言错误,在release模式下不会出现,但在debug模式下几乎是必现。原因嘛,打开Eigen给出的网址可以明确:数据结构未对齐(unaligned arrays)。这个问题对于刚接触openMVG的人来说还是很烦人的,openMVG代码很优雅,很多数据类型都是从模板类或函数延伸,通过虚函数扩展各项具体方法,而且非常强烈的依赖Eigen这个库,所以给定位问题带来了阻碍。经过一天的攻坚,最后大概确认了原因:

regionsh这个文件中定义的Regions类包含了fixed-size vectorizable Eigen types的stl容器vector,按照Eigen提供的解决方法,需要做的是:

//原来

typedef std::vector<FeatureT> FeatsT;

//改成

typedef std::vector<FeatureT, Eigen::aligned_allocator<FeatureT>> FeatsT;

//其它类似的地方都要改,包括返回vector的函数,最好也加上 EIGEN_MAKE_ALIGNED_OPERATOR_NEW

#1 核心库

#11 图像

#Image Container

openMVG提供一个基本的类用作图像容器:Image<T>,T代表像素类型,这个类可以处理灰度,RGB,RGBA或者自定义类型的图像。用法很简单:

// A 8-bit gray image:

Image<unsigned char> grayscale_image_8bit;

// Multichannel image: (use pre-defined pixel type)

// A 8-bit RGB image:

Image<RGBColor> rgb_image_8bit;

// 8-bit RGBA image

Image<RGBAColor> rgba_image_8bit;

Image<Rgba<unsigned char> > rgba_image2_8bit;

这里的 RGBColor,RGBAColor等是openMVG基于Eigen定义好的类型,具体是定义在pixel_typeshpp中。

#Image I/O

openMVG支持ppm/pgm,jpeg,png,tiff格式的文件,例子:

Image<RGBColor> rgb_image_gray;

bool bRet = ReadImage("FooimgExtension", &rgb_image);

#Drawing operations

用于在图像上画圆,椭圆,直线等。

#12 数值

openMVG重新包装了Eigen的基本类型和算法,以便更简单的调用。比如 Vec2代表一个二维点(char型)。

#13 特征

这个模块主要是提供特征容器的封装,包括特征,特征描述,关键点集等,基本都是模板类,比如顶一个sift特征描述子可以这样做:

// SIFT like descriptor

typedef Descriptor<float, 128> siftDescriptorData;

#14 相机

此模块提供不同的相机模型的抽象类,包括:

#小孔相机模型

最简单的相机模型,如图: 相机模型包括内参和外参,关键词也就是大家熟悉的几样:投影矩阵,旋转、平移矩阵,焦距、主点等,具体参见说明。 看一个例子:openMVG提供的PinholeCamera类:

/// Pinhole camera P = K[R|t], t = -RC

struct PinholeCamera

{

//构造函数

PinholeCamera(

const Mat3 & K = Mat3::Identity(),

const Mat3 & R = Mat3::Identity(),

const Vec3 & t = Vec3::Zero())

: _K(K), _R(R), _t(t)

{

_C = -Rtranspose() t;

P_From_KRt(_K, _R, _t, &_P);

}

PinholeCamera(const Mat34 & P)

{

_P = P;

KRt_From_P(_P, &_K, &_R, &_t);

_C = -_Rtranspose() _t;

}

/// Projection matrix P = K[R|t]

Mat34 _P;

/// Intrinsic parameter (Focal, principal point)

Mat3 _K;

/// Extrinsic Rotation

Mat3 _R;

/// Extrinsic translation

Vec3 _t;

/// Camera center

Vec3 _C;

};

#15 多视角几何

这部分是比较基础和重要的模块之一,包括了:

多视角集几何中n(>=2)视角的求解算法;

将这些求解算法综合起来以便进行鲁棒估计的通用框架——Kernel;

文档中讲解了单应矩阵,本征矩阵,本质矩阵,位置矩阵等的概念,讲得非常好,建议仔细阅读文档。 简单的解释一下:

单应矩阵:描述两个投影平面之间的关系;

本征矩阵:同一个场景在两个相机成像下的关系,也就是物体上的点A在两个视角下成像位置的关系;

本质矩阵:基于本征矩阵和内参矩阵建立,描述相机和本征矩阵位置之间的相对关系;

位置矩阵:估计相机的绝对位置(被转化为一个最小化问题求解);

Kernel:一个将求解器、数据、度量方案等结合起来的类,这个类将用于鲁棒的估计以上的参数和矩阵;

#16 线性规划

一个用于求解多视角几何中线性优化(参数估计)的工具集,文档。

#17 鲁棒估计

提供一些列鲁棒估计方法,比如:Max-Consensus,Max-Consensus,AC-Ransac A Contrario Ransac等。

#17 匹配

提供的接口包括:NNS,K-NN,FLANN,KVLD,Cascade hashing Nearest Neighbor等。这些接口可用于在二维或三维点集,以及更高维的特征描述集中。

#18 追踪

多视几何里的追踪是指在一系列的中找到对应的特征点(同一点在不同视角下的位置)。

#19 sfm

openMVG提供的sfm模块包含了处理SfM问题的一系列方法个数据存储接口,例如相机位置估计,结构测量,BA等。 SfM_Data类包含了SfM所有的输入:

struct SfM_Data

{

/// Considered views

Views views; // 包含图像文件名,id_view,id_pose,id_intrinsic,image size。

/// Considered poses (indexed by viewid_pose)

Poses poses; // 相机的三维位置

/// Considered camera intrinsics (indexed by viewid_cam)

Intrinsics intrinsics; // 相机内参

/// Structure (3D points with their 2D observations)

Landmarks structure; // 二维视图特征关联的3D点

}

下面是例子:

#1 features_siftPutativeMatches

这个样例做了这么几件事(直接翻译官方):

分别提取两张图像的SIFT特征(使用非免费的vlsift)并形成特征描述;

根据特征描述子匹配两张图像上的特征点(BRUTE_FORCE_L2方法);

展示匹配结果;

刚开始的时候会遇到Assertion failed断言错误,处理办法见上一篇文章。运行成功项目目录下会生成三个文件:00_imagesjpg,01_featuresjpg,02_siftMatchessvg。

#2 features_affine_demo

这个例子是图像MSER(参考)和TBMR特征提取的样例,MSER(Maximally Stable Extremal Regions)最大极值稳定区域是一种对图像灰度具有仿射变换不变性,也许也是这个样例起名的原因。TBMR(tree-based Morse regions)这个算法不是特别了解,具体可以在google学术中搜索。

#3 features_image_matching

这个样例给出了利用Image_describer接口提取特征描述子,并匹配和显示结果的样例。示例中可以选择SIFT,AKAZE_MLDB或者AKAZE算法,AKAZE介绍可看这里,是一种比SIFT更稳定的特征检测算法。程序中关于解析输入参数的部分可以注释掉(如果你是用过VS2013 debug),直接修改sImage_describer_type这个值以测试。

#4 features_kvld_filter 和 features_repeatability

这两个也是关于特征提取和匹配的,kvld这个例子中由于之前更改了regionsh中的内容,所以有些函数接口也要做相应改变,具体也是在vector中增加对齐函数选项。

#5 multiview_robust_homography_guided 和 multiview_robust_fundamental_guided

这两个样例是估计单应矩阵和本征矩阵的,并且能够根据这些信息反过来确定匹配点。两个样例运行时间都很长(分辨率教大时),第一个在用另外的照片时还遇到报错,大概是在DoG时出错,具体也没有细究了·····

#6 exif_Parsing

提取EXIF信息,编译后通过命令行执行,给出的参数格式:--imafile 你的照片路径,路径中使用/斜杠。

另一篇:learn openMVG-安装和简介

#7 multiview_robust_essential

估计本质矩阵并计算3D结构。这个例子可以直接运行,生成的点云十分稀疏且不带颜色信息。

OpenMVG (open Multiple View Geometry):开源多视角立体几何库,这是一个cv届处理多视角立体几何的著名开源库,信奉逗简单,可维护地,提供了一套强大的接口,每个模块都被测试过,尽力提供一致可靠的体验。

地址:github

文档:documents

openMVG能够:

解决多视角立体几何的精准匹配问题;

提供一系列SfM需要用到的特征提取和匹配方法;

完整的SfM工具链(校正,参估,重建,表面处理等);

openMVG尽力提供可读性性强的代码,方便开发者二次开发,核心功能是尽量精简的,所以你可能需要其它库来完善你的系统。openMVG分成了几个大的模块:

核心库:各个功能的核心算法实现;

样例:教你怎么用;

工具链:也就是连起来用咯(乱序图像集的特征匹配,SfM,处理色彩和纹理);

#0 安装(win10+VS2013)

第一步当然是从github clone代码,然后按照 BUILD 说明 *** 作,需要注意的是:

template <class T> inline T operator|(T x, T y){

return static_cast<T>(static_cast<int>(x) | static_cast<int>(y));

};

建议和opencv一起编译,方法是在CMakeListstxt文件中修改相应选项为 ON,然后在cmake的GUI中添加一个叫OpenCV_DIR的入口,值就是你已经安装好的opencv的路径。

openMVG写的非常不错,对Windows也提供了良好的支持,所以cmake之后用VS打开生成的openMVGsln解决方案就可以进行编译了,编译的时间稍久。我用的VS2013不支持C++新特性:constexpr,所以建议你使用VS2015或更新版本,如果一定要用VS2013,可以这样做:在src/openMVG/cameras/Camera_Commonhpp文件中将有constexpr的地方直接去掉,或者改成模板函数也是可以的:

运行样例,这里遇到一个坑:DenseStoraageh line 86报错:R6010 Assertion failed,这是一个断言错误,在release模式下不会出现,但在debug模式下几乎是必现。原因嘛,打开Eigen给出的网址可以明确:数据结构未对齐(unaligned arrays)。这个问题对于刚接触openMVG的人来说还是很烦人的,openMVG代码很优雅,很多数据类型都是从模板类或函数延伸,通过虚函数扩展各项具体方法,而且非常强烈的依赖Eigen这个库,所以给定位问题带来了阻碍。经过一天的攻坚,最后大概确认了原因:

regionsh这个文件中定义的Regions类包含了fixed-size vectorizable Eigen types的stl容器vector,按照Eigen提供的解决方法,需要做的是:

//原来

typedef std::vector<FeatureT> FeatsT;

//改成

typedef std::vector<FeatureT, Eigen::aligned_allocator<FeatureT>> FeatsT;

//其它类似的地方都要改,包括返回vector的函数,最好也加上 EIGEN_MAKE_ALIGNED_OPERATOR_NEW

#1 核心库

#11 图像

#Image Container

openMVG提供一个基本的类用作图像容器:Image<T>,T代表像素类型,这个类可以处理灰度,RGB,RGBA或者自定义类型的图像。用法很简单:

// A 8-bit gray image:

Image<unsigned char> grayscale_image_8bit;

// Multichannel image: (use pre-defined pixel type)

// A 8-bit RGB image:

Image<RGBColor> rgb_image_8bit;

// 8-bit RGBA image

Image<RGBAColor> rgba_image_8bit;

Image<Rgba<unsigned char> > rgba_image2_8bit;

这里的 RGBColor,RGBAColor等是openMVG基于Eigen定义好的类型,具体是定义在pixel_typeshpp中。

#Image I/O

openMVG支持ppm/pgm,jpeg,png,tiff格式的文件,例子:

Image<RGBColor> rgb_image_gray;

bool bRet = ReadImage("FooimgExtension", &rgb_image);

#Drawing operations

用于在图像上画圆,椭圆,直线等。

#12 数值

openMVG重新包装了Eigen的基本类型和算法,以便更简单的调用。比如 Vec2代表一个二维点(char型)。

#13 特征

这个模块主要是提供特征容器的封装,包括特征,特征描述,关键点集等,基本都是模板类,比如顶一个sift特征描述子可以这样做:

// SIFT like descriptor

typedef Descriptor<float, 128> siftDescriptorData;

#14 相机

此模块提供不同的相机模型的抽象类,包括:

#小孔相机模型

最简单的相机模型,如图: 相机模型包括内参和外参,关键词也就是大家熟悉的几样:投影矩阵,旋转、平移矩阵,焦距、主点等,具体参见说明。 看一个例子:openMVG提供的PinholeCamera类:

/// Pinhole camera P = K[R|t], t = -RC

struct PinholeCamera

{

//构造函数

PinholeCamera(

const Mat3 & K = Mat3::Identity(),

const Mat3 & R = Mat3::Identity(),

const Vec3 & t = Vec3::Zero())

: _K(K), _R(R), _t(t)

{

_C = -Rtranspose() t;

P_From_KRt(_K, _R, _t, &_P);

}

PinholeCamera(const Mat34 & P)

{

_P = P;

KRt_From_P(_P, &_K, &_R, &_t);

_C = -_Rtranspose() _t;

}

/// Projection matrix P = K[R|t]

Mat34 _P;

/// Intrinsic parameter (Focal, principal point)

Mat3 _K;

/// Extrinsic Rotation

Mat3 _R;

/// Extrinsic translation

Vec3 _t;

/// Camera center

Vec3 _C;

};

#15 多视角几何

这部分是比较基础和重要的模块之一,包括了:

多视角集几何中n(>=2)视角的求解算法;

将这些求解算法综合起来以便进行鲁棒估计的通用框架——Kernel;

文档中讲解了单应矩阵,本征矩阵,本质矩阵,位置矩阵等的概念,讲得非常好,建议仔细阅读文档。 简单的解释一下:

单应矩阵:描述两个投影平面之间的关系;

本征矩阵:同一个场景在两个相机成像下的关系,也就是物体上的点A在两个视角下成像位置的关系;

本质矩阵:基于本征矩阵和内参矩阵建立,描述相机和本征矩阵位置之间的相对关系;

位置矩阵:估计相机的绝对位置(被转化为一个最小化问题求解);

Kernel:一个将求解器、数据、度量方案等结合起来的类,这个类将用于鲁棒的估计以上的参数和矩阵;

#16 线性规划

一个用于求解多视角几何中线性优化(参数估计)的工具集,文档。

#17 鲁棒估计

提供一些列鲁棒估计方法,比如:Max-Consensus,Max-Consensus,AC-Ransac A Contrario Ransac等。

#17 匹配

提供的接口包括:NNS,K-NN,FLANN,KVLD,Cascade hashing Nearest Neighbor等。这些接口可用于在二维或三维点集,以及更高维的特征描述集中。

#18 追踪

多视几何里的追踪是指在一系列的中找到对应的特征点(同一点在不同视角下的位置)。

#19 sfm

openMVG提供的sfm模块包含了处理SfM问题的一系列方法个数据存储接口,例如相机位置估计,结构测量,BA等。 SfM_Data类包含了SfM所有的输入:

struct SfM_Data

{

/// Considered views

Views views; // 包含图像文件名,id_view,id_pose,id_intrinsic,image size。

/// Considered poses (indexed by viewid_pose)

Poses poses; // 相机的三维位置

/// Considered camera intrinsics (indexed by viewid_cam)

Intrinsics intrinsics; // 相机内参

/// Structure (3D points with their 2D observations)

Landmarks structure; // 二维视图特征关联的3D点

}

下面是例子:

#1 features_siftPutativeMatches

这个样例做了这么几件事(直接翻译官方):

分别提取两张图像的SIFT特征(使用非免费的vlsift)并形成特征描述;

根据特征描述子匹配两张图像上的特征点(BRUTE_FORCE_L2方法);

展示匹配结果;

刚开始的时候会遇到Assertion failed断言错误,处理办法见上一篇文章。运行成功项目目录下会生成三个文件:00_imagesjpg,01_featuresjpg,02_siftMatchessvg。

#2 features_affine_demo

这个例子是图像MSER(参考)和TBMR特征提取的样例,MSER(Maximally Stable Extremal Regions)最大极值稳定区域是一种对图像灰度具有仿射变换不变性,也许也是这个样例起名的原因。TBMR(tree-based Morse regions)这个算法不是特别了解,具体可以在google学术中搜索。

#3 features_image_matching

这个样例给出了利用Image_describer接口提取特征描述子,并匹配和显示结果的样例。示例中可以选择SIFT,AKAZE_MLDB或者AKAZE算法,AKAZE介绍可看这里,是一种比SIFT更稳定的特征检测算法。程序中关于解析输入参数的部分可以注释掉(如果你是用过VS2013 debug),直接修改sImage_describer_type这个值以测试。

#4 features_kvld_filter 和 features_repeatability

这两个也是关于特征提取和匹配的,kvld这个例子中由于之前更改了regionsh中的内容,所以有些函数接口也要做相应改变,具体也是在vector中增加对齐函数选项。

#5 multiview_robust_homography_guided 和 multiview_robust_fundamental_guided

这两个样例是估计单应矩阵和本征矩阵的,并且能够根据这些信息反过来确定匹配点。两个样例运行时间都很长(分辨率教大时),第一个在用另外的照片时还遇到报错,大概是在DoG时出错,具体也没有细究了·····

#6 exif_Parsing

提取EXIF信息,编译后通过命令行执行,给出的参数格式:--imafile 你的照片路径,路径中使用/斜杠。

另一篇:learn openMVG-安装和简介

#7 multiview_robust_essential

估计本质矩阵并计算3D结构。这个例子可以直接运行,生成的点云十分稀疏且不带颜色信息。

setp1

安装CodeX,不解释,在AppStop中搜索安装即可

setp2

安装Homebrew

Homebrew即MacOSX上的apt-get

按照官网的安装方式,在terminal中输入下列命令即可完成安装

cd ~

ruby -e "$(curl -fsSL >

以上就是关于HartSift: 一种基于GPU的高准确性和实时SIFT全部的内容,包括:HartSift: 一种基于GPU的高准确性和实时SIFT、sift特征向量的维数、viola jones人脸检测原理等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9642836.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存