三维重建一直是计算机视觉的热点研究领域,是获取物体模型及三维场景的重要手段。人们获取物体三维信息的方法有很多种,比如传统的几何造型技术,此方法需要较好的专业水平和大工作量;还可以通过3D激光扫描技术来获取,此方法受室外环境的影响较大,且不能获得目标纹理信息。相比而言,基于图像特征点的三维重建方法没有上述建模方法的诸多限制,只需要输入图像,成本低廉,不需要其他特殊的先验信息,通过优秀先进的算法,就能恢复出图像中物体及场景的三维信息。不仅所需设备简单,对场景的限制较小,而且还能够获得精确逼真的模型。
总结来说,本文围绕基于图像特征点的三维重建做了如下工作:
(1)了解相机成像模型的相关知识,尤其是重建相关坐标系和针孔相机模型的相关知识。
(2)采用鲁棒性较强的SIFT算法完成了特征点的提取,并且使用最近邻方法辅助SIFT算法完成了特征点匹配。使用Bundle Adjustment来完成优化调整,最终可以获得重建的稀疏三维点云。
(3)在了解稠密重建相关方法的基础上,选择PMVS来完成稠密重建。经过种子面片的提取,重复进行重建、扩展的过程,最后通过过滤,重建出目标的稠密三维点云。
(4)对得到的点云和网格在MeshLab软件中进行一系列的后处理过程,包括清除杂点、网格化、恢复流行边缘、参数化、投影纹理等过程,得到一个更为形象的三维模型。
本项目采用的是基于运动恢复结构(英文全称:Structure from Motion,简称SFM)的三维重建方法,数据输入是二维图像,目的是重建出三维模型。主要流程分为五步:
(1)图像获取,项目使用的图像是在光照条件大致相同的情况下,使用手机对一目标物体以不同角度拍摄的照片。
(2)特征点检测与匹配,使用SIFT特征匹配算法。并使用选择式图像匹配策略,在图像对的特征匹配过程进行优化,减少特征匹配的时间成本,最后使用RANSAC方法去除误匹配,使匹配结果更加精确。
(3)相机参数求解。本项目使用的是SFM下的相机求解方法,在不精确的初始化情况下,利用bundle adjustment约束, 求得精确的相机参数,并得到稀疏的点云模型。
(4)稠密点云的三维重建,使用较为流行的PMVS算法。项目利用SFM得到的稀加粗样式疏点云和相机参数,通过PMVS基于面片生成的三维重建算法,生成稠密匹配下的三维点云模型。
(5)MeshLab优化处理,通过对PMVS得到的点云进行泊松表面重建,以得到更好的三维模型。
VisualSFM在读取图片时,会根据图片中的EXIF信息计算每一张照片的相机内参。EXIF信息是相机在拍照的时候自动保存在照片中的,一定要确保照片中的EXIF信息没有丢失,否则图像匹配和重建的效果会非常差。
拍摄图片的注意事项:
(1)采集图像的过程中,相机共中心能拼接全景,要以待重建的对象为中心,围着它每转10-20度拍一张,这样转一圈,有不同高度信息更好,同时在相邻照片中保留更多的相同景物。VisualSFM没有照片数量限制,照片越多,重建出的细节越丰富,但重建过程花费时间的会越长。
(2)尽量有序地采集照片,这样在使用VisualSFM进行match的时候,不用进行全局match,只需要使用“SfM->Pairwise matching->Compute Sequence Match”就可以了。使用这种匹配模式,需要设置一个参数n,照片只会和最近的n张照片进行匹配,可以节省很多时间。
(2)近的n张照片进行匹配,可以节省很多时间。
2.2.1.SIFT原理
SIFT算法, 又称尺度不变特征转换。SIFT 特征是一种局部特征,它在旋转、尺度以及亮度上都有很好的不变性,且在视角变化,仿射变换和噪声等方面,都能具有较好的鲁棒性。
SIFT特征算法分为三个步骤:
(1)利用尺度空间,进行极值检测。
(2)特征点定位,对特征方向赋值,并对特征点描述。
(3)特征点匹配。
(1)构建尺度空间–建立高斯差分金字塔
SIFT算法的图像处理是基于尺度空间的,这样做的目的是为了模拟图像的多尺度特性。SIFT算法使用高斯卷积来进行尺度空间的构建。
首先将图像进行处理,构建不同层次的尺度。对每一个尺度,独立编号。高斯卷积内核可以线性的实现尺度变换,因此使用它描述尺度空间。描述形式如下;
L(x, y, σ) = G(x, y, σ) *l(x,y)
其中,G(x, y, σ)是尺度可变的高斯函数,
(x,y)为空间坐标,I(x,y)为点(x,y)在图像Ⅰ中的对应坐标。σ是尺度坐标,为0时表示原始图像,σ值越小,图像的分辨率越高,细节特征越明显。通过对原始图像依次进行不同尺度的高斯模糊和降采样,可以构造出图像金字塔,金字塔的层级从0开始,第0层表示原始图像。在高斯金字塔中的每组中相邻两层相减(下一层减上一层)就生成高斯差分金字塔。
(2)空间极值点检测
在图像金字塔中,除了首尾两层图像和图像的边缘点,每一个像素点的DoG值都要与邻域空间内其他像素点DoG值相比较。如图3所示,中间的检测点和它的26个邻域点进行比较,若该点的DoG值在领域中是极值,则该点的坐标和尺度会作为该点的特征信息被记录下来。
(3)特征点描述符生成
基于检测到的特征点的相关信息,可以生成该特征点的描述符。通常的做法是以此点为中心,选取8x8的矩形窗口。如图4(a),黑点表示将要进行描述的关键点。每个小格代表了其邻域内的一个像素,箭头表示该像素的梯度,有方向和大小。圆表示高斯加权的计算范围。在关键点的位置进行分割,在每个4×4的子窗口中,对于每个梯度进行8个方向上的分解,并计算各方向的累加值。这样每个子窗口都生成一个种子点。如图4(b)所示,一个关键点由4个种子点组成,共32个梯度信息。这种邻域信息综合的方法能提高噪声抗性,增强稳定性。
每个点L(x,y)的梯度的模m(x,y)以及方向0(x,y)可通过下面公式求得:
在实际的计算过程中,为进一步消除光照影响、保证匹配的效果,使用16×16的窗口来生成描述符。描述符有16个种子点,128维的梯度信息。这样的描述符包含的信息比较丰富,独特性也较好,采用适当的方法对其进行匹配,可以实现较精确的配对。
图4:关键点描述符生成过程
(a)关键点领域内的梯度方向 (b)关键点描述符
2.2.2.特征点匹配
提取特征点后,得到其特征向量,接下来要对特征进行匹配,来获取图像 2.2.3. 去除误匹配 由于图像中很容易出现重复纹理和颜色的情况,所以在特征匹配的过程中 2.2.4.操作步骤 操作:点击“SfM-Pairwise Matching-Compute Missing Matching”或者直接点击状态栏中的 ,等待右侧任务栏出现”Totally xx seconds used”,说明SIFT特征提取与匹配完成。 2.2.5. 过程分析 完成了特征匹配之后,就要进行稀疏重建,稀疏重建实质上是将匹配的特征 2.3.1.光束平差法 在求解特征点三维坐标的时候,由于噪声点和计算误差等因素,求得的相机参数以及三维坐标会有偏差。这种偏差会对最后的三维重建结果产生很大的影响。为了提高结果的精度,必须要处理在测量以及计算中产生的误差。光束法平差(bundle adjustment, 简称BA),是一种非常有效的处理这类误差的方法。对场景中任意三维点P,从每个视图所对应的摄像机光心发射出来并经过图像中P’对应的像素点的光线,原则上来说都应交于P一点;实际过程中由于噪声等存在,每条光线几乎不可能汇聚与一点, 因此在求解过程中,需要不断对待求信息进行调整,使得所有光线最终能都交于点P。对于空间中每个点的三维坐标和相机光学中心“发射”出的光束,光束法平差通过这些光束对结构和相机参数进行调节,获得三维空间结构及相机参数的最优解。光束法平差是SFM稀疏三维重建的最后一步,也是非常重要的一步。它在给定相机内部参数的基础上,通过最小化重投影误差,在非线性最小二乘意义下,对相机参数及图像中的三维结构进行高精度重建。 2.3.2.操作步骤 操作:点击Sfm ->Reconstruct Sparse或者直接点击状态栏中的 2.3.3.过程分析 利用SFM方法, 通过迭代求解出相机参数和三维点坐标。即重建出3D模型的稀疏点云。若有“bad” 相机(位置错误或朝向错误),结合工具栏上的“3+”按钮和手型按钮即可删除之,使结果更准确。 每个相机 每个点实体 (2)0000xxxx.txt文件: 格式如下(内容如图11所示): “CONTOUR” :文件头,P[3][4]表示一个3*4的投影矩阵; 事实上,在SFM过程中,我们用来做重构的点是通过特征检测和匹配得到 2.4.1.面片的重构 PMVS (Patch-based Mutilview Stereo),又称基于面片的多视角立体视 1.初始化特征匹配 首先用DOG和Harris来提取图像的角点特征,即为每幅图像的特征点。对于图像Ii,以及其对应的光心O(Ii),该图像中的特征点f,通过允许有两个像素误差的极线约束找到它在其他图像中的同种类型的特征点f′,构成匹配点对(f,f′)。然后用这些匹配点对使用三角化的方法生成一系列三维空间点,然后将这些点按照距离O(Ii)从小到大顺序进行排列,然后依次尝试生成面片,直到成功。 2.面片扩散(patch expansion) 面片生成的目的就是保证每个图像块至少对应一个面片。通过上面生成的面片,重复得生成新的面片,具体来说就是给定一个面片p,首先获得一个满足一定条件的邻域图像块集合C(p),然后进行面片生成的过程。 3.面片过滤(patch filtering) 2.4.2.操作过程 操作:选择"Sfm->Reconstruct Dense" 或者点击图标 2.4.3.过程分析 稠密重建后在根目录下生成.ply文件,如图12所示: 至此,VisualSFM 的工作告一段落,结果都已存盘。可以得到照片的p矩阵(投影矩阵),保存在一个txt文件夹下的0000xxxx.txt文件中(如图11所示); 在visualize文件夹下是纠正过后的影像文件,如图13所示。若因图片匹配失败或图片较少导致某区域重建失败或重建出的某区域细节不足,可以返回添加一些该区域的照片重新来过,但因特征检测和匹配的结果已存盘(每张图像对应的.sift和. mat文件),所以已经匹配好的图像不必再次匹配,会更快完成。 最后会在根目录下生成 **.nvm.cmvs文件夹,其中有个00文件夹,这个文件夹就是使用meshlab显示三维模型所需要的输入,其中option-0000.ply的文件则记录的是三维重建后物体三维坐标。如图14所示: 经过这一系列三维重建流程后,可以得到图像中场景的稠密点云模型。为了能够更好的表现实体模型的性质,我们往往要对其进行网格化处理。为了得到更好的模型,我们对得到的点云在MeshLab软件中进行一系列的后处理过程,包括清除杂点、网格化、恢复流行边缘、参数化、投影纹理等过程,得到一个更为形象的三维模型。
之间像素的一一对应关系。使用最近邻匹配算法(Nearest Neighbor,NN)进行特征匹配。彩色图像具有更多的信息,这些信息在进行特征匹配的时候,很容易引入误差。因此常常在最开始将图像转换成灰度图像,以消除误差。
特征匹配中的最近邻算法(Nearest Neighbor,NN)具体算法过程如下:
(1)对图像1中的特征向量v,找到图像2中与该特征向量距离最近的两个向量v1,v2,距离上v1
常会出现误匹配的情况。而三维重建过程中需要稳定准确的特征点,误匹配
出现会使计算结果产生严重的误差,对重建结果造成严重的影响。所以去除
匹配是特征匹配过程中一个重要的步骤,去除误匹配使用RANSAC ( Random Sampleonsensus) 算法,该算法又称随机采样一致性算法。
RANSAC算法经常被用于处理包含异常值的数据集,剔除异常值,并得到可靠的模型。在特征匹配过程中,RANSAC算法流程大体相同:
(1)对图像进行特征点检测与匹配,得到匹配好的特征点对集合
(2)随机选取8组点对,用其计算基础矩阵F。
(3)计算特征点集中的特征点对是否满足对极约束的阈值要求,若偏差小于阈值,则认为是正确的匹配点对;反之则认为是误匹配,将其剔除。统计匹配点对个数,并将其作为内点集;
(4)在内点集中继续抽样迭代求解基础矩阵F,重新搜索匹配特征,重复此过程。最后选择具有最大正确匹配点数的基本矩阵。
VisualSFM会自动的把特征提取和特征匹配保存在盘中,为每幅图像保存文件名为特征提取[name].sift和特征匹配[name].mat,[name].sift存储所有的检测到的SIFT特征,[name].mat存储特征匹配。
如果想改变特征提取的参数,并且重新运行重建,需要删除所有相关的[name].sift和[name].mat文件。如果想去返回读取匹配的结果,检查匹配文件代码 here,或者你可以使用 “SfM->Pairwise Matching->Export F-Matrix Matches”。2.3.SFM稀疏点云重建
点还原到三维空间中。
运动恢复结构(Structure From Motion, SFM),是指在相机内部参数已知的情况下,计算相机的外部参数,并恢复图像的三维结构。SFM 过程需要使用前期匹配得到的特征点对和相机参数,来对特征点的三维信息进行求解。其具体流程如下所示:
(1)获取相机内参矩阵,可以对输入图像其内部的EXIF信息获取相机的焦距,用来计算内参矩阵。
(2)特征点检测与匹配,通过特征点检测和匹配算法来得到双视图之间精准的点对应关系。
(3)计算双视图之间的基本矩阵和本质矩阵,通过匹配到的特征点对以及双视图之间的对极约束来计算双视图之间的基本矩阵,并和(1)中获得的相机内参计算出本质矩阵。
(4)通过对本质矩阵进行奇异值分解(SVD),得到相机之间的外参数矩阵,即相机之间的运动(旋转矩阵和平移矩阵)。
(5)通过三角测量计算出特征点的三维坐标。(三角测量是指通过在两处观察同一点的夹角,进而来确定该点的位置关系)。
(6)利用光束法平差BA(Bundle Adjustment)来对得到的相机参数和三维坐标点进行优化,得到精确的相机参数和空间点坐标,最后得到稀疏的点云模型。
这时光束法平差(Bundle Adjustment)步骤就会自动的使用多核光束法平差(Multicore Bundle Adjustment)等待右侧任务栏出现”Totally xx seconds used”,说明稀疏重建完成。
(1)bundle文件。稀疏重建完成之后,会得到一个形式为bundle_.out格式的.out文件(一般称为bundle文件),如图5所示,这个bundle文件中保存了图像的参数、投影矩阵和空间点的三维坐标。
bundle_.out文件格式如下:
# Bundle file v0.3
[相机1]
[相机2]
…
[相机N]
[点1]
[点2]
…
[点M]
[相机焦距,两个径向畸变多项式系数]
[一个3X3矩阵:代表相机旋转]
[一个3维向量:描述摄像机平移]
如图6所示:
在计算过程中,会生成一个名叫list 的文本文件,如图所示,其中记录了图像的名称,
图7:list.txt文件
图8:list.txt文件内容
[3维向量描述该点的三维位置]
[3维向量描述该点的RGB颜色]
view list存放的是每一个点的详细信息。第一个参数:能观察到该点的相机个数。之后以< camera > < key > < x >< y >四个参数参数为一组依次写入。其中:< camera >为相机(图片)索引,< key >为keypoint序列索引,< x >< y >为该keypoint在图片上的二维坐标。
某个点实体
图9
图10:0000xxxx.txt文件
图11:0000xxxx.txt文件内容
CONTOUR
P[0][0] P[0][1] P[0][2] P[0][3]
P[1][0] P[1][1] P[1][2] P[1][3]
P[2][0] P[2][1] P[2][2] P[2][3]
[ x, y, z, 1 ] : 三维点的齐次坐标
[ u, v, 1 ] :图片投影点的二维齐次坐标
d: 关于照相机的点的深度
对应于相机坐标系和世界坐标系的关系:
可以看出,矩阵P为相机内参矩阵与外参矩阵的乘积。2.4.PMVS稠密点云重建
的,特征点所具有的特点使其是天生不密集的,所以通过SFM过程最后得到的
是稀疏的点云模型,不可能直接得到稠密的点云。为得到稠密的点云模型,我
们需要利用PMVS或者CMVS和PMVS进行计算。
完成稀疏重建之后,将进行点云的加密以获取稠密三维点云。稠密重建过程的数据源是bundle文件和图片集。稠密重建首先将稀疏重建的结果转换成稠密重建的输入,输入文件包含了相机参数以及相关的设置信息。获取了bundle文件之后,经过预处理使用PMVS或者CMVS和PMVS进行加密处理,得到稠密点云数据。图像数量较大时,计算过程复杂,计算量大,可以先用CMVS对照片进行聚类, 以减少稠密重建数据量,再使用PMVS对划分后的子集进行重建,最后进行合并从而得到完成的稠密点云。
觉,此算法也是稠密重建算法中效果最好的算法之一。其主要流程有如下三步:
(1)初始化特征匹配,初始化特征匹配是为了生成一系列稀疏的面片,并要多次执行,同时进行筛选,以保证生成足够稠密的合格的面片。一般来说,PMVS 使用的是SFM得到的结果来作为输入来生成面片。
(2)面片生成。
(3)面片筛选。
尝试生成面片的方法如下所示:首先初始化候选面片的c(p),n(p)和R(p)。c(p)为面片的中心点,通过它的指向观测方向的垂直向量,称为法向量,记为n(p)。R(p)为p的参考图像。
如下所示:
由于生成的面片可能有很多错误的情况,因此我们认为在图像 Ii中可见的面片是面片的法向量与面片中心到相机光心的连线夹角小于一定角度 α的图像,即满足:
上式中,V(p)表示准可见图像集,意思是应该能看到p,但实际中可能无法识别或被遮挡的图像集。
同样,实际看到p的可见图像集v*(p),也通过相同的方法获得;
h表示光照差异性函数。
这样面片的信息都已经初始化过了,然后对c (p)和 n(p)进行优化,并将优化过后的c (p)和 n(p)带入上述公式对V(p)和V"(p)进行更新。如果|V*(p)≥y,即认为面片p的可视图像至少为y幅,即接受面片p,重建成功。并将面片p存储到对应的可视图像的图像块中(即更新Qi(x,y)和Q(x,y))。
下面是面片p的两个相关概念:
图像块邻域C(p):
面片 p和p′的临近关系:
即当面片 pp和p′p′满足上式时,即判定两者为临近关系,上式中的 ρ1由 Rp在 c(p)和c(p′)中的深度决定。
当存在一个面片p′其所属的图像块 Ci(x′,y′)满足 Ci(x′,y′)∈Cp,同时 p和p′属于近邻关系时,此时将Ci(x′,y′)从 C(p)中删除,不对他进行面片生成。同时,即使这个条件没有满足,只要 Qi(x′,y′)不为空,也不需要再此图像块上执行生成操作。
对于 C(p)中其余的图像块,将会执行面片生成的操作流程以生成新的面片 p′。首先用 p的相应变量初始化p′的 n(p′)、R(p′)和V(p′),对于c(p’)的初始值为穿过 Ci(x,y)的可视光线与面片 p所在平面的交点。使用
由 V§得到 V∗(p′),再由上面提到的方法对 c(p′)和n(p′)进行优化。在优化的过程中,将 c(p′)约束在一条直线上,使得 p′在图像 Ii上的位置不会改变,始终对应的是 Ci(x,y)。优化完成后,给 V(p′)加上一组图像,这些图像块会根据深度测试判断为p′对其应该是可见的,并根据此更新 V∗(p′)。
最终如果 |V∗(p′)|≥r,则判定 p′是可接受的,即生成成功,同时更新 Qi(x,y)和 Q∗i(x,y)。
在面片的重建过程中,可能会生成一些误差较大的面片,因此需要过滤来确保面片的准确性。
第一个过滤器是通过可视一致性进行过滤,令Up表示与当前可视信息不连续的面片集合,所谓的不连续就是p和p′两个面片不属于近邻关系,但是却存在于同一个Qi(x,y)中。对于Up中的面片p,如果满足下列条件,则将其过滤掉。
直观上来讲,如果p是一个异常值,那么1−g∗§和|V∗p|都会比较小,这样p一般都会被过滤掉。
第二个过滤器同样也是考虑可视一致性,不过会更加严格,对于每个面片p,我们计算他通过深度测试得到的可视图像的总数,如果数目小于r,那么则认为p是异常值,从而过滤掉。
第三个过滤器,对于每个面片p,在Vp中,收集这样的一组面片,他们的映射到面片p自己所在的图像块以及所有相邻的图像块,如果p的八邻域内的面片数量占收集所得面片数量的比例小于0.25,则任务是异常值,将其过滤掉。
等待右侧任务栏出现”Totally xx seconds used”,说明稠密重建完成。
稠密重建使用的是PMVS/CMVS。这时会被提示保存[name].nvm 文件,并且CMVS将会在文件[name].nvm.cmvs中运行,如果把重建保存为[name].nvm 文件,则[name].i.ply就是第i个模型的结果。
图 122.5.三维重建流程总结分析
图13
图142.6.MeshLab优化处理