主要内容

结构运动从多个视图

结构与运动的过程(SfM)估计一个场景的三维结构的二维视图。它被用在许多应用程序,比如机器人导航、自动驾驶和增强现实。这个例子向您展示了如何估计校准相机的姿势从一系列的观点,并重建场景的三维结构未知比例因子。

概述

这个例子展示了如何重构三维场景的序列二维视图用相机校准使用相机校准器。这个例子使用了一个imageviewset对象来存储和管理与每个视图相关的数据,如摄像机构成和图像点,以及从双视图之间的匹配点。

示例使用两两匹配点估计当前视图的摄像机构成相对于前面的视图。然后链接两两匹配到长点跟踪生成多个视图使用findTracks的方法imageviewset对象。这些轨迹作为输入多视图使用的三角测量triangulateMultiview功能和相机的姿态和3 d场景的优化点使用bundleAdjustment函数。

例子包括两个主要部分:相机运动估计和密集的场景重建。在第一部分,估计摄像机构成为每个视图的例子使用稀疏点集匹配整个视图。在第二部分,再次遍历序列视图的例子中,使用vision.PointTracker跟踪整个视图、密集点集来计算一个密集的场景的三维重建。

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

  1. 连续每一对图片,找到一组对应点。这个例子使用检测兴趣点detectSURFFeatures函数,提取特征描述符使用extractFeatures功能,发现匹配使用matchFeatures函数。或者,您可以跟踪整个视图使用的点vision.PointTracker

  2. 估计的相对构成当前视图,这是相机方向和位置相对于前面的视图。示例使用一个helper函数helperEstimateRelativePose,电话estimateEssentialMatrixestrelpose

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

  4. 存储当前视图属性:摄像机构成和图像点。

  5. 商店之间的内围层匹配之前和当前视图。

  6. 找点跟踪到目前为止所有视图处理。

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

  8. 使用bundleAdjustment函数优化相机姿态和3 d点。存储精制相机的姿势imageviewset对象。

读输入图像序列

读取和显示图像序列。

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

图包含一个坐标轴对象。坐标轴对象标题输入图像序列包含一个类型的对象的形象。

负载相机参数

加载cameraParameters对象创建使用相机校准器

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

创建一个视图包含第一个视图设置

使用一个imageviewset对象来存储和管理图像点和相机的姿势与每个视图,以及之间的匹配对观点。一旦你填充一个imageviewset对象,您可以使用它来找到跟踪多个观点和检索相机使用triangulateMultiviewbundleAdjustment功能。

%得到相机的内在参数intrinsic = cameraParams.Intrinsics;% Undistort第一形象。I = undistortImage(图片{1},intrinsic);%检测功能。“NumOctaves”有助于检测大规模增加%在高分辨率图像特征。使用一个ROI来消除虚假的%图像的边缘特征。边境= 50;投资回报率=[边境,边境,大小(我,2)- 2 *边境,边界大小(我,1)- 2 *);prevPoints = detectSURFFeatures (NumOctaves = 8,我投资回报率(ROI);%提取特征。使用“正直”特性提高了匹配,只要%摄像机运动涉及很少或没有平面旋转。prevFeatures = extractFeatures(我prevPoints直立= true);%创建一个空imageviewset对象来管理相关的数据%的观点。vSet = imageviewset;%添加第一个视图。与第一个视图相关联的摄像机%和原点,面向沿z轴。viewId = 1;vSet = addView (vSet viewId rigidtform3d,分= prevPoints);

添加其他的观点

经过图像的其余部分。为每一个图像

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

  2. 估计当前视图的摄像机构成相对于前面的视图。

  3. 计算当前视图的摄像机构成全球坐标系相对于第一个视图。

  4. 满足最初的3 d世界。

  5. 使用包调整完善所有相机姿态和3 d世界点。

我= 2:元素个数(图片)% Undistort当前图像。I = undistortImage(图片{我},intrinsic);%检测、提取和匹配特性。currPoints = detectSURFFeatures (NumOctaves = 8,我投资回报率(ROI);currFeatures = extractFeatures(我currPoints直立= true);indexPairs = matchFeatures (prevFeatures currFeatures,独特MaxRatio = 0.7, = true);%选择匹配点。matchedPoints1 = prevPoints (indexPairs (: 1));matchedPoints2 = currPoints (indexPairs (:, 2));%估计当前视图的相机构成相对于前面的视图。%的计算规模,这意味着之间的距离%的相机在前面的视图和当前视图设置为1。%这将被捆绑调整修正。[relPose, inlierIdx] = helperEstimateRelativePose (matchedPoints1、matchedPoints2 intrinsic);%得到包含前面的摄像机构成的表。.AbsolutePose prevPose =姿势(vSet张);%计算当前相机构成全球坐标系统%相对于第一个视图。currPose = rigidtform3d (prevPose.A * relPose.A);%设置当前视图添加到视图。vSet = addView (vSet我currPose点= currPoints);%之前存储之间的匹配点和当前视图。vSet = addConnection (vSet,张,我、relPose匹配= indexPairs (inlierIdx:));%找到跟踪所有观点。跟踪= findTracks (vSet);%获得所有视图包含相机带来的表。坎波斯=姿势(vSet);%满足初始点位置的3 d世界。xyzPoints = triangulateMultiview(追踪,坎波斯,intrinsic);%改进3 d世界分和相机的姿势。[xyzPoints,坎波斯,reprojectionErrors] = bundleAdjustment (xyzPoints,痕迹,坎波斯,intrinsic FixedViewId = 1,PointsUndistorted = true);%存储精制相机姿势。vSet = updateView (vSet campos);prevFeatures = currFeatures;prevPoints = currPoints;结束

显示相机的姿势

点显示精制相机姿态和3 d世界。

%显示相机的姿势。坎波斯=姿势(vSet);图;plotCamera(坎波斯,大小= 0.2);持有%排除嘈杂的3 d点。goodIdx = (reprojectionErrors < 5);xyzPoints = xyzPoints (goodIdx:);%显示3 d点。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);标题(“精制相机姿势”);

计算密集的重建

再通过图像。这次检测一组致密的角落,并在所有视图使用跟踪它们vision.PointTracker

%阅读和undistort第一形象I = undistortImage(图片{1},intrinsic);%检测角落的形象。prevPoints = detectMinEigenFeatures(我MinQuality = 0.001);%创建重点跟踪对象跟踪点在视图。追踪=愿景。PointTracker (MaxBidirectionalError = 1, NumPyramidLevels = 6);%初始化跟踪点。prevPoints = prevPoints.Location;初始化(prevPoints追踪,我);%存储在视图中密集点集。vSet = updateConnection (vSet, 1, 2,匹配= 0 (0,2));vSet = updateView (vSet 1分= prevPoints);%跟踪点在所有视图。我= 2:元素个数(图片)%阅读和undistort当前图像。I = undistortImage(图片{我},intrinsic);%跟踪点。[currPoints, validIdx] =步骤(追踪,我);%清楚之间的匹配点。如果我<元素个数(图像)vSet = updateConnection (vSet,我,我+ 1,匹配= 0 (0,2));结束vSet = updateView (vSet,分= currPoints);%点匹配存储在视图集。匹配= repmat((1:尺寸(prevPoints, 1))”, [1, 2]);匹配=匹配(validIdx:);vSet = updateConnection (vSet,张,我匹配=匹配);结束%找到跟踪所有观点。跟踪= findTracks (vSet);%找到跟踪所有观点。坎波斯=姿势(vSet);%满足初始点位置的3 d世界。xyzPoints = triangulateMultiview(追踪,坎波斯,intrinsic);%改进3 d世界分和相机的姿势。[xyzPoints,坎波斯,reprojectionErrors] = bundleAdjustment (xyzPoints,追踪,坎波斯,intrinsic FixedViewId = 1,PointsUndistorted = true);

显示密度重建

显示摄像机姿态和密集的点云。

%显示精制相机的姿势。图;plotCamera(坎波斯,大小= 0.2);持有%点排除嘈杂的3 d世界。goodIdx = (reprojectionErrors < 5);%显示点密集的3 d世界。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);标题(“密集的重建”);

引用

[1]M.I.A. Lourakis和嗜Argyros (2009)。SBA:一个软件包为通用稀疏捆调整”。ACM交易数学软件(ACM) 36(1):行。

[2]r·哈特利a . Zisserman“计算机视觉中的多视图几何,”剑桥大学出版社,2003年。

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