主要内容

单眼视觉测程法

视觉测量是通过分析一系列图像来确定相机的位置和方向的过程。视觉径管用于各种应用,例如移动机器人,自驾车和无人驾驶航空车。此示例向您展示了如何从一系列图像估算单个校准相机的轨迹。

概述

这个例子展示了如何从一个2-D视图序列估计校准相机的轨迹。本例使用筑波大学的CVLAB创建的新筑波立体数据集的图像。(https://cvlab.cs.tsukuba.ac.jp)。数据集由计算机图形生成的合成图像组成,包括地面真实相机的姿态。

如果没有额外的信息,单目摄像机的轨迹只能恢复到一个未知的比例因子。用于移动机器人或自动驾驶车辆的单目视觉里程计系统通常从另一个传感器(如车轮里程表或GPS)或场景中已知大小的物体获得比例因子。这个例子是从地面真实值计算比例因子。

该示例分为三个部分:

  1. 估计相对于第一视图的第二视图的姿态。通过估计基本矩阵并将其分解成相机位置和方向来估计第二视图的姿势。

  2. 使用全局捆绑调整引导估计相机轨迹。使用eMipolar约束消除异常值。查找从前两个视图和当前视图三角化的点之间的3D到2D对应关系。通过解决透视-N点(PNP)问题来计算当前视图的世界相机姿势。估计相机的姿势不可避免地导致累积随时间累积的错误。调用这种效果漂流.为了减少漂移,本例使用束调整对目前估计的所有姿态进行了改进。

  3. 使用加窗束调整估计摄像机剩余轨迹。随着每一个新的视图,改进所有姿势的时间都在增加。窗口束调整是一种通过优化最后一个来减少计算时间的方法n而不是整个轨迹。通过不为每个视图调用bundle调整,计算时间进一步减少。

读取输入图像序列和地面真相

的图像新的Tsukuba立体声数据集由筑波大学的CVLAB创造。如果您在自己的作品或出版物中使用这些图片,请引用以下论文:

[1] Martin Peris Martorell,Atsuto Maki,Sarahartull,Yasuhiro Ohkawa,Kazuhiro Fukui,“朝着模拟驱动的立体声视觉系统”。ICPR,PP.1038-1042,2012年的诉讼程序。

[2] Sarah Martull, Martin Peris Martorell, Kazuhiro Fukui,“基于地面真实视差图的真实CG立体图像数据集”,ICPR workshop TrakMark2012, pp.40- 42,2012。

images = imagedataStore(fullfile(toolboxdir(“愿景”),“visiondata”“NewTsukuba”));加载地面真实相机姿势。load(fullfile(toolboxdir(“愿景”),“visiondata”“visualOdometryGroundTruth.mat”));

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

用A.imageviewset.对象来存储和管理与每个视图相关联的图像点和摄像机姿态,以及视图对之间的点匹配。一旦你填充了imageviewset.对象,您可以使用它来查找跨多个视图的点轨迹,并检索要使用的相机姿势triangulateMultiviewbundleAdjustment功能。

%创建一个空的imageviewset对象来管理与每个视图关联的数据。vset = imageviewset;%读取并显示第一张图像。IRGB = ReadImage(图像,1);玩家= Vision.videoplayer(“位置”, [20, 400, 650, 510]);步骤(球员,Irgb);

属性中使用camera intrinsics创建camera intrinsics对象%新的Tsukuba数据集。focalLength = [615 615];%以像素为单位指定principalPoint = [320 240];百分比像素[x,y]图象尺寸大小= (Irgb [1, 2]);%(像素)[mrows, ncols]内在=摄像石(FocalLength,Principalpoint,Imageize);

转换为灰度和不失真。在这个例子中,不失真没有效果,因为图像是合成的,没有镜头失真。然而,对于真实的图像,不失真是必要的。

prevI = undistortion timage (im2gray(Irgb), intrinsics); / /本质%检测功能。prevpoints = detectsurfeatures(previ,'米兰克斯德', 500);%选择一个特征子集,均匀分布在整个图像中。numPoints = 200;prevPoints = selectUniform(prevPoints, numPoints,大小(prevI));%提取特征。使用“直立”功能可提高匹配质量相机的运动很少或没有涉及到面内旋转。prevFeatures = extractFeatures(prevI, prevPoints,“正直”, 真的);%添加第一个视图。放置与第一个视图相关联的摄像机%在原点,沿z轴方向。viewid = 1;vset = addview(vset,viewid,rigid3d(眼睛(3),[0 0 0]),“点”,prevpoints);

绘制初始摄像机姿态

根据新筑波数据集的地面真实数据,创建两个图形相机对象,代表估计和实际相机姿态。

%设置坐标轴。图轴([-220,50,-140,20,-50,300]);%设置y轴垂直向下。甘氨胆酸视图(3);集(gca),“CameraUpVector”, [0, - 1,0]);甘氨胆酸camorbit (-120 0'数据', [0,1, 0]);网格包含(“X (cm)”);ylabel(“Y (cm)”);zlabel (“Z (cm)”);持有%绘图估计相机姿势。cameraSize = 7;camPose =姿势(vSet);camEstimated = plotCamera (camPose,“大小”cameraSize,......“颜色”‘g’'不透明度', 0);绘制实际摄像机姿态。camActual = plotCamera (“大小”cameraSize,“AbsolutePose”......rigid3d (groundTruthPoses。定位{1}、groundTruthPoses.Location {1}),......“颜色”'B''不透明度', 0);初始化摄像机轨迹。轨迹估计= plot3(0,0,0,“g -”);轨迹= plot3(0,0,0,“b -”);传奇(“估计轨迹”“实际轨迹”);标题(“相机轨迹”);

估计第二视图的姿态

从第二视图检测和提取功能,并将它们与第一个视图匹配helperdetectandmatchfatecures..相对于第一个视图估计第二视图的姿势HelperestimaterElativepose,并将其添加到imageviewset.

%读取并显示图像。viewId = 2;Irgb = readimage(images, viewwid);步骤(球员,Irgb);

%转换为灰度和不失真。i = undostortimage(IM2Gray(IM2Gray(IRGB),内在);以前和当前图像之间的%匹配功能。[Furports,Currfeatures,IndexPairs] = HelperDetectandMatchFeatures(......prevFeatures,我);%估计当前视图的姿势相对于前一个视图。[orient, loc, inlierIdx] = helperEstimateRelativePose(......prevPoints (indexPairs (: 1)), currPoints (indexPairs (:, 2)), intrinsic);%排除极线异常值。indexPairs = IndexPairs(Inlieridx,:);将当前视图添加到视图集。vSet = addView(vSet, viewId, rigid3d(orient, loc)),“点”,curports);%存储前一个视图和当前视图之间的点匹配。vSet = addConnection(vSet, viewId-1, viewId,)“匹配”, indexPairs);

相对于第一视图的第二视图的位置只能恢复到未知的比例因子。使用地面真相计算比例因子Helpernormalizeviewset.,模拟外部传感器,将用于一个典型的单目视觉里程计系统。

vSet = helperNormalizeViewSet(vSet, groundtruthpose);

更新摄像机轨迹图使用helperUpdateCameraPlotshelperUpdateCameraTrajectories

helperupdatecameraplot (viewId, camEstimated, camActual, pose (vSet),......groundTruthPoses);Helperupdatecameratories(查看id,溯极,TrajectoryActial,......姿势(vSet) groundTruthPoses);

prevI =我;prevFeatures = currFeatures;prevpoints = curptpoints;

使用全局束平差的Bootstrap相机轨迹估计

找出前两个视图中三角化的世界点与当前视图中的图像点之间的3d到2d对应关系。使用helperFindEpipolarInliers查找满足极线约束的匹配项,然后使用helperFind3Dto2DCorrespondences将前两个视图中的三维点进行三角剖分,并在当前视图中找到相应的二维点。

通过求解透视-n点(PnP)问题,计算当前视图的世界相机位姿estimateWorldCameraPose.对于前15个视图,使用全局bundle调整来完善整个轨迹。对有限数量的视图使用全局bundle调整将引导估计相机轨迹的其余部分,而且这并不昂贵。

viewId = 3:15%读取并显示下一个图像Irgb = readimage(images, viewwid);步骤(球员,Irgb);%转换为灰度和不失真。i = undostortimage(IM2Gray(IM2Gray(IRGB),内在);%先前图像和当前图像之间的匹配点。[Furports,Currfeatures,IndexPairs] = HelperDetectandMatchFeatures(......prevFeatures,我);%消除特征匹配中的异常值。Inlieridx = Helperfindepipolinliers(prevpoints(IndexPairs(:,1)),......FurrPoints(IndexPairs(:,2)),内在机构);indexPairs = IndexPairs(Inlieridx,:);从前面两个视图中三角化点,并找到%当前视图中对应的点。[worldPoints, imagePoints] = helperfind3dto2d通信(vSet,......intrinsic、indexPairs currPoints);由于RANSAC涉及一个随机过程,它有时可能不会达到期望的置信水平,并超过的最大数目%试验。自结果是以来发生这种情况时会禁用警告%仍然有效。警告State =警告(“关闭”'愿景:Ransac:maxtrialsReached');估计当前视图的世界相机姿态。[orient, loc] = estimateWorldCameraPose(imagePoints, worldPoints, intrinsics);%恢复原来的警告状态警告(warningstate)将当前视图添加到视图集。vSet = addView(vSet, viewId, rigid3d(orient, loc)),“点”,curports);%存储前一个视图和当前视图之间的点匹配。vSet = addConnection(vSet, viewId-1, viewId,)“匹配”, indexPairs);跟踪= findTracks (vSet);查找点轨迹跨越多个视图。坎波斯=姿势(vSet);为所有视图设置相机姿势。三角定位三维世界点的初始位置。xyzPoints = triangulateMultiview(tracks, campose, intrinsics);使用束调整优化相机姿态。[〜,野营] = Bundleadjustment(XYZPOINTS,轨道,野营,......内在机构,'obessundistorted',真的,“AbsoluteTolerance”1 e-12......“RelativeTolerance”1 e-12“MaxIterations”, 200,“FixedViewID”1);vSet = updateView(vSet, camPoses);%更新视图集。% Bundle调整可以移动整个摄像机集。规范化的%查看设置,以将第一台相机放在沿着的原点% z轴和调整比例,以匹配的地面真相。vSet = helperNormalizeViewSet(vSet, groundtruthpose);%更新摄像机轨迹图。helperupdatecameraplot (viewId, camEstimated, camActual, pose (vSet),......groundTruthPoses);helperUpdateCameraTrajectories (viewId trajectoryEstimated,......trajectoryActual,姿势(vSet) groundTruthPoses);prevI =我;prevFeatures = currFeatures;prevpoints = curptpoints;结束

使用窗口捆绑调节估算剩余的相机轨迹

通过使用窗口捆绑调整估计剩余的相机轨迹,仅限于最后15个视图,以限制计算量。此外,每个视图都不需要捆绑调整,因为estimateWorldCameraPose以与三维点相同的单位计算姿态。本节为每7个视图调用bundle调整。实验选择了调用束调整的窗口大小和频率。

viewId = 16:元素个数(images.Files)%读取并显示下一个图像Irgb = readimage(images, viewwid);步骤(球员,Irgb);%转换为灰度和不失真。i = undostortimage(IM2Gray(IM2Gray(IRGB),内在);%先前图像和当前图像之间的匹配点。[Furports,Currfeatures,IndexPairs] = HelperDetectandMatchFeatures(......prevFeatures,我);从前面两个视图中三角化点,并找到%当前视图中对应的点。[worldPoints, imagePoints] = helperfind3dto2d通信(vSet,......intrinsic、indexPairs currPoints);由于RANSAC涉及一个随机过程,它有时可能不会达到期望的置信水平,并超过的最大数目%试验。自结果是以来发生这种情况时会禁用警告%仍然有效。警告State =警告(“关闭”'愿景:Ransac:maxtrialsReached');估计当前视图的世界相机姿态。[orient, loc] = estimateWorldCameraPose(imagePoints, worldPoints, intrinsics);%恢复原来的警告状态警告(warningstate)将当前视图和连接添加到视图集。vSet = addView(vSet, viewId, rigid3d(orient, loc)),“点”,curports);vSet = addConnection(vSet, viewId-1, viewId,)“匹配”, indexPairs);%使用窗口束调整优化估计的相机姿态。运行%优化每7次查看。如果mod(viewId, 7) == 0找到过去15个视图中的点轨迹并进行三角定位。windowSize = 15;startFrame = max(1, viewId - windowSize);track = findTracks(vSet, startFrame:viewId);campose = pose (vSet, startFrame:viewId);[xyzPoints, reprojErrors] = triangulateMultiview(tracks, campose, intrinsics); / /播放视频保持前两个姿势固定,保持相同的比例。fixedIds = [startFrame, startFrame+1];%排除了具有高重注错误的点和曲目。idx = reprojErrors < 2;[~, camPoses] = bundleAdjustment(xyzPoints(idx,:), tracks(idx),......坎波斯,intrinsic“FixedViewIDs”,固定性,......'obessundistorted',真的,“AbsoluteTolerance”1 e-12......“RelativeTolerance”1 e-12“MaxIterations”,200);vSet = updateView(vSet, camPoses);%更新视图集。结束%更新摄像机轨迹图。helperupdatecameraplot (viewId, camEstimated, camActual, pose (vSet),......groundTruthPoses);helperUpdateCameraTrajectories (viewId trajectoryEstimated,......trajectoryActual,姿势(vSet) groundTruthPoses);prevI =我;prevFeatures = currFeatures;prevpoints = curptpoints;结束

持有离开

概括

此示例显示了如何从一系列视图中估算校准单眼相机的轨迹。请注意,估计的轨迹与基础事实不完全匹配。尽管相机姿势的非线性细化,但相机姿势估计中的错误累积,导致漂移。在视觉测量系统中,通常通过从多个传感器的信息融合信息来解决该问题,并且通过执行循环闭合来解决。

参考

[1] Martin Peris Martorell,Atsuto Maki,Sarahartull,Yasuhiro Ohkawa,Kazuhiro Fukui,“朝着模拟驱动的立体声视觉系统”。ICPR,PP.1038-1042,2012年的诉讼程序。

[2] Sarah Martull, Martin Peris Martorell, Kazuhiro Fukui,“基于地面真实视差图的真实CG立体图像数据集”,ICPR workshop TrakMark2012, pp.40- 42,2012。

[3] m.i.a.卢克西斯和A.A.argyros(2009)。“SBA:用于通用稀疏捆绑调整的软件包”。数学软件(ACM)36(1):1-30的ACM交易。

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

[5] B. Triggs;P. Mclauchlan;R. Hartley;A. FitzGibbon(1999)。“捆绑调整:现代合成”。视觉算法国际研讨会的诉讼程序。Springer-Verlag。第298-372页。

[6] X.-S。高,X.-R。侯俊华,唐俊华,侯俊华。程,“透视-三点问题的完整解决方案分类”,IEEE Trans。模式分析与机器智能,vol. 25, no. 28,页930-943,2003。