主要内容

结构从运动从多个视角

运动结构(SfM)是从一组二维视图中估计一个场景的三维结构的过程。它被用于许多应用,如机器人导航、自动驾驶和增强现实。这个例子向您展示了如何从一系列视图中估计经过校准的相机的姿态,并根据未知的比例因子重建场景的3-D结构。

概述

该示例演示如何从用摄像机拍摄的二维视图序列重建三维场景相机校准器.该示例使用了imageviewset对象来存储和管理与每个视图相关的数据,例如相机姿势和图像点,以及来自视图对的点之间的匹配。

该示例使用成对点匹配来估计当前视图相对于前一个视图的摄像机姿态。然后将成对匹配链接到跨越多个视图的更长的点跟踪findTracks的方法imageviewset对象。然后,这些轨迹作为多视图三角测量的输入triangulateMultiview功能和改进的相机姿态和三维场景点使用bundleAdjustment函数。

该实例包括两个主要部分:摄像机运动估计和密集场景重建。在第一部分中,该示例使用跨视图匹配的稀疏点集估计每个视图的相机姿势。在第二部分中,示例再次遍历视图序列,使用愿景。PointTracker来跟踪视图中密集的点集,计算场景的密集三维重建。

摄像机运动估计算法由以下步骤组成:

  1. 对于每一对连续的图像,找到一组对应的点。方法检测兴趣点detectSURFFeatures方法提取特征描述符extractFeatures函数,并使用matchFeatures函数。或者,您可以使用愿景。PointTracker

  2. 估计当前视图的相对姿态,这是相对于前一个视图的相机方向和位置。该示例使用了一个helper函数helperEstimateRelativePose,电话estimateEssentialMatrix而且estrelpose

  3. 将当前视图的相对位姿转换为序列的第一个视图的坐标系。

  4. 存储当前视图属性:相机姿势和图像点。

  5. 存储前一个视图和当前视图之间的内嵌匹配。

  6. 在目前处理过的所有视图中查找点轨迹。

  7. 使用triangulateMultiview函数,计算与轨迹对应的初始三维位置。

  8. 使用bundleAdjustment功能,以完善相机姿势和3-D点。存储精致的相机姿势imageviewset对象。

读取输入图像序列

读取并显示图像序列。

使用|imageDatastore|获取目录中所有图像文件名的列表。imageDir = fullfile (toolboxdir (“愿景”),“visiondata”...“structureFromMotion”);imd = imageDatastore (imageDir);显示图片。图蒙太奇(imd)。文件,“大小”, 3, 2);将图像转换为灰度。image = cell(1, numel(imds.Files));i = 1:numel(imds. files) i = readimage(imds, i);{我}= im2gray图像(i);结束标题(输入图像序列的);

图中包含一个axes对象。标题为Input Image Sequence的axes对象包含一个类型为Image的对象。

负载相机参数

加载cameraParameters对象创建的。相机校准器

data =加载(fullfile (imageDir“cameraParams.mat”));cameraParams = data.cameraParams;

创建一个包含第一个视图的视图集

使用一个imageviewset对象来存储和管理与每个视图关联的图像点和相机姿势,以及视图对之间的点匹配。一旦你在imageviewset对象,您可以使用它来跨多个视图查找点轨迹,并检索要使用的相机姿势triangulateMultiview而且bundleAdjustment功能。

获取相机的内在参数intrinsic = cameraParams.Intrinsics;还原第一张图片。I = undistortion timage(图像{1},intrinsic);%检测功能。增加“NumOctaves”有助于大规模检测%特征在高分辨率图像中。使用ROI来消除虚假信息%的特征在图像的边缘周围。边境= 50;roi = [border, border, size(I, 2)- 2*border, size(I, 1)- 2*border];prevPoints = detectsurfeatures (I, NumOctaves=8, ROI= ROI);%提取特征。使用“直立”功能可以改善匹配,只要相机运动很少或没有平面内旋转。。prevFeatures = extractFeatures(I, prevPoints, vertical =true);创建一个空的imageviewset对象来管理与每个视图相关的数据%的观点。vSet = imageviewset;添加第一个视图。放置与第一个视图相关联的相机%和原点,沿z轴方向。viewId = 1;vSet = addView(vSet, viewId, rigidtform3d, Points=prevPoints);

添加其余的视图

浏览剩下的图像。为每一个图像

  1. 先前图像和当前图像之间的匹配点。

  2. 估计当前视图相对于前一个视图的相机姿势。

  3. 相对于第一个视图,在全局坐标系中计算当前视图的相机姿态。

  4. 对初始的三维世界点进行三角定位。

  5. 使用束调整来完善所有的相机姿势和3-D世界点。

我= 2:元素个数(图片)恢复当前图像的失真。I = undistortion timage (images{I}, intrinsic);检测、提取和匹配特征。currPoints = detectSURFFeatures(I, NumOctaves=8, ROI= ROI);currFeatures = extractFeatures(I, currPoints, vertical =true);indexPairs = matchFeatures(prevFeatures, currFeatures,...独特MaxRatio = 0.7, = true);%选择匹配点。matchedPoints1 = prevPoints(indexPairs(:, 1));matchedPoints2 = currPoints(indexPairs(:, 2));%估计当前视图相对于前一个视图的相机姿势。这个姿势是按比例计算的,意思是指%表示上一个视图和当前视图中的摄像机的百分比。这将通过捆绑调整得到修正。。[relPose, inlierIdx] = helperEstimateRelativePose(...matchedPoints1、matchedPoints2 intrinsic);获取包含前一个相机姿势的表。prevPose = pose (vSet, i-1).AbsolutePose;在全局坐标系中计算当前相机的姿态%相对于第一个视图。currPose = rigidtform3d (prevPose.A * relPose.A);将当前视图添加到视图集。vSet = addView(vSet, i, currPose, Points=currPoints);%存储前一个视图和当前视图之间的点匹配。vSet = addConnection(vSet, i-1, i, relPose, Matches=indexPairs(inlierIdx,:));在所有视图中查找点跟踪。跟踪= findTracks (vSet);获取包含所有视图的相机姿势的表。坎波斯=姿势(vSet);对3d世界点的初始位置进行三角定位。。xyzPoints = triangulateMultiview(tracks, campose, intrinsic);完善3d世界点和相机姿势。。[xyzPoints, campose, reprojectionErrors] = bundleAdjustment(xyzPoints,...轨道,campose, intrinsic, FixedViewId=1...PointsUndistorted = true);存储精致的相机姿势。vSet = updateView(vSet, campose);prevFeatures = currFeatures;prevPoints = currPoints;结束

显示相机的姿势

显示精致的相机姿势和3d世界点。

显示相机姿势。坎波斯=姿势(vSet);图;plotCamera(坎波斯,大小= 0.2);持有排除有噪声的三维点。。goodIdx = (reprojectionErrors < 5);xyzPoints = xyzPoints(goodIdx,:);显示3d点。pcshow (xyzPoints VerticalAxis =“y”VerticalAxisDir =“下来”MarkerSize = 45);网格持有%指定查看卷。loc1 = camPoses.AbsolutePose (1) .Translation;xlim ([loc1 (1) 5, loc1 (1) + 4]);ylim ([loc1 (2) 5, loc1 (2) + 4]);zlim ([loc1 (3) 1, loc1 (3) + 20));camorbit (0, -30);标题(“精制相机姿势”);

计算密集的重建

再看一遍这些图像。这一次检测密集的角集,并跟踪它们在所有视图使用愿景。PointTracker

读取并还原第一张图片。I = undistortion timage(图像{1},intrinsic);在第一张图像中检测角落。prevPoints = detectMinEigenFeatures(I, MinQuality=0.001);创建点跟踪器对象来跟踪跨视图的点。追踪=愿景。PointTracker(MaxBidirectionalError=1, NumPyramidLevels=6);初始化点跟踪器。prevPoints = prevPoints.Location;初始化(prevPoints追踪,我);在视图集中存储密集点。vSet = updateConnection(vSet, 1,2, Matches= 0 (0,2));vSet = updateView(vSet, 1, Points=prevPoints);跟踪所有视图中的点。我= 2:元素个数(图片)读取并恢复当前图像的失真。I = undistortion timage (images{I}, intrinsic);跟踪分数。[currPoints, validIdx] = step(跟踪器,I);清除点之间的旧匹配。。如果i < numel(images) vSet = updateConnection(vSet, i, i+1, Matches= 0 (0,2));结束vSet = updateView(vSet, i, Points=currPoints);在视图集中存储点匹配。matches = repmat((1:size(prevPoints, 1))', [1,2]);matches = matches(validIdx,:);vSet = updateConnection(vSet, i-1, i, Matches= Matches);结束在所有视图中查找点跟踪。跟踪= findTracks (vSet);在所有视图中查找点跟踪。坎波斯=姿势(vSet);对3d世界点的初始位置进行三角定位。。xyzPoints = triangulateMultiview(tracks, campose,...intrinsic);完善3d世界点和相机姿势。。[xyzPoints, campose, reprojectionErrors] = bundleAdjustment(...xyzPoints, tracks, campose, intrinsic, FixedViewId=1...PointsUndistorted = true);

显示密度重建

显示相机姿势和密集的点云。

显示精致的相机姿势。图;plotCamera(坎波斯,大小= 0.2);持有排除嘈杂的3d世界点。。goodIdx = (reprojectionErrors < 5);显示密集的3d世界点。。pcshow (xyzPoints (goodIdx:), VerticalAxis =“y”VerticalAxisDir =“下来”MarkerSize = 45);网格持有%指定查看卷。loc1 = camPoses.AbsolutePose (1) .Translation;xlim ([loc1 (1) 5, loc1 (1) + 4]);ylim ([loc1 (2) 5, loc1 (2) + 4]);zlim ([loc1 (3) 1, loc1 (3) + 20));camorbit (0, -30);标题(“密集的重建”);

参考文献

M.I.A. Lourakis和A.A. Argyros(2009)。“SBA:通用稀疏包调整软件包”。ACM数学软件学报36(1):1-30。

R. Hartley, A. Zisserman,“计算机视觉中的多视图几何”,剑桥大学出版社,2003年。

[3] b区格;p . McLauchlan;r·哈特利;菲茨吉本(1999)。“捆绑调整:现代综合”。视觉算法国际研讨会论文集。斯普林格出版社。298 - 372页。

Baidu
map