Windows上快速运行ORB-SLAM2:编译资源与避坑指南

发布时间:2026/10/4 11:51:48
Windows上快速运行ORB-SLAM2:编译资源与避坑指南 简介Windows下跑通ORBSLAM实验为需要快速搭建ORB-SLAM环境的计算机视觉开发者提供了一站式方案解决VS下第三方依赖编译繁琐、配置路径复杂的问题压缩包共898个文件约154.62MB以头文件、C源码、lib/dll链接库和VS属性表为主含yaml配置文件和20张张氏标定板图片导入工程后简单配置即可运行。资源已有362人学习下载适合SLAM入门及二次开发。除可直接运行的工程外还包括词袋文件、单目示例和标定图片便于完成从环境配置、相机标定到SLAM运行的完整实验博主还提供微信答疑遇到问题可及时获得帮助。1. Windows 跑 ORB-SLAM 不是玄学一份编译好的资源能让你少走一周弯路ORB-SLAM 在 Linux 上是「一条命令跑通」的经典项目但换到 Windows 就是另一回事Eigen 内存对齐、g2o 的usleep缺失、DBoW2 词典加载失败任何一个环节都能卡你一个下午。这份资源的价值在于它把 Eigen、g2o、DBoW2、Pangolin 这些第三方库全部编译完成并存成了属性表意味着最难的环境搭建已经替你趟平。你拿到手要做的不是从零编译而是把工程挂上去、改好路径、跑起来再用附带的 20 张张氏标定板图片完成相机标定最后基于封装好的My_Monocular.cc做二次开发。这篇文章我会把整个流程拆成可复现的步骤包括参数怎么设、坑在哪、失败时看什么适合正在做视觉 SLAM 课程设计、毕设或者刚接触 ORB-SLAM2 的从业者。2. 这份资源里到底有什么按文件清单对号入座先把资源的内容盘一遍别急着解压就开跑。我习惯拿到包先列目录搞清楚每一块对应什么环节后面出了问题也知道去哪翻。你下载到的这份里几个关键东西是这么对应的文件/目录在 ORB-SLAM 流程里的角色你要做的事AdolcForward、AlignedVector3、ArpackSupport、Array、AutoDiff、Cholesky这些是 Eigen 3.3.x 的头文件子模块ORB-SLAM 的 g2o 和 Sophus 都依赖它们做矩阵运算和自动求导确认它们和Eigen主目录放一起别只拷一半BVH这是 OpenGV 或 Pangolin 在某些版本里依赖的包围体层次结构头文件编译 relocalization 相关代码时必需缺失会报找不到BVH/BVH.hppos_specific.cg2o 在 Windows 上用来替代 Unix 系统调用的兼容文件不用改但别从工程里删掉ORBvoc.binORB 词典文件词袋回环检测的底库约 28MB运行时必须能定位到它路径不能带中文My_Monocular.cc修改过的主程序入口单目 SLAM 的启动文件学它怎么调ORB_SLAM2::System约 20 张张氏标定板图片不同角度的棋盘格照片用于计算相机内参标定实验的输入素材这里单独说一下 Eigen 那组文件。Array、AutoDiff是 Eigen 的unsupported模块里的AlignedVector3、ArpackSupport是稀疏求解和内存对齐需要的任何一份第三方库编译产物里这几样通常是成套出现的。如果你从别处拼凑 Eigen最常见的问题就是少了unsupported文件夹编译时报Eigen/Cholesky: No such file or directory。这其实不是路径写错是文件本身不全。所以你拿到这份资源后先核对这几个目录都在再谈配置。这套东西的版本认证我在第 3 章末尾给你一个检测命令一条命令就能确认 Eigen 能不能用。My_Monocular.cc是全包最值得读的文件。它从argc/argv拿词典路径、配置路径、图像序列路径然后构建ORB_SLAM2::System再循环读帧调用mpSystem-TrackMonocular(im, timestamp)。这套流程和官方mono_tum.cc几乎一致区别在于封装程度更高后面第 6 章细讲它哪里可以改。3. 环境配置与工程挂接属性表为什么能省一下午Windows 下编译 ORB-SLAM2 的第一步是把第三方库装对。这份资源最省事的一点是Eigen、g2o、DBoW2、Pangolin、OpenCV 这些全部编译完成并导出成了属性表。你拿到后要做的不是再编译一遍而是把工程属性挂到这个表上。3.1 先对齐版本为什么 Eigen 3.3.x 不能随便换ORB-SLAM2 的Thirdparty/g2o在 Windows 上用 CMake 编译时默认对接的 Eigen 版本是 3.3.x。如果你手上正好有 Eigen 3.4 甚至更新的版本会发现编译 g2o 时一路顺畅但跑起来偶发崩溃。原因在于 3.4 开始 Eigen 对vectorization和内存对齐策略做了调整而 g2o 的Solver和OptimizableGraph里硬编码了对齐假设。这种问题很隐蔽它不是编译错是运行时的内存对齐崩溃。所以我建议先执行下面这个验证命令把 Eigen 的核心版本打出来grep -n define EIGEN_WORLD_VERSION\|define EIGEN_MAJOR_VERSION\|define EIGEN_MINOR_VERSION Eigen/src/Core/util/Macros.h这条命令的目的不是跑着玩而是确认你用的对。输出如果是3 3 7和 ORB-SLAM2 官方测试版本一致可以放心。如果你拿到的这份资源里 Eigen 是 3.3.x就不用折腾升级属性表是按这个版本导出的换版本反而容易翻车。这里加一句提醒如果你打算把这份资源用在别的项目里Eigen 3.4 的问题边界是「SLAM 系统本身崩但 OpenCV 正常」出现这种状况先回来查版本别急着改算法。还有一点ORB-SLAM2 用的是#include Eigen/Core这种全局路径所以你的 VC 包含目录必须指到Eigen父目录不是指到 Eigen 目录里面。3.2 属性表挂接步骤一秒切换 Debug/Release 配置拿到这份包之后标准的做法是建一个ORB_SLAM2解决方案把源码加进去然后把属性表加到工程上。属性表是个.props文件它内部写死了包含目录、库目录、附加依赖项。我在工程里一般是这么挂的Project 的 PropertySheet 节点下手动编辑 .vcxproj Import Project..\Thirdparty\ORB_SLAM2.props /这个props文件里会定义类似这样的内容我这里给一份常见的简版具体以你手上的为准PropertyGroup LabelUserMacros IncludePath$(SolutionDir)Thirdparty\eigen;$(SolutionDir)Thirdparty\g2o;$(SolutionDir)Thirdparty\DBoW2;$(OpenCV3_DIR)include/IncludePath LibraryPath$(SolutionDir)lib;$(OpenCV3_DIR)\x64\vc15\lib/LibraryPath /PropertyGroup ItemDefinitionGroup Link AdditionalDependenciesopencv_world340.lib;g2o.lib;DBoW2.lib;Pangolin.lib;%(AdditionalDependencies)/AdditionalDependencies /Link /ItemDefinitionGroup先解释这段干啥IncludePath让编译器能找到全部头文件LibraryPath让链接器去lib目录找静态库AdditionalDependencies列出需要链接的库。你在 IDE 里右键工程 - 添加现有属性表选中这份.props保存后 Debug 和 Release 都能用同一份。设置完后不要急着编译先做一次干净的验证新建一个空 C 工程写一个最简单的 Eigen 和 OpenCV 混合代码#include Eigen/Dense #include opencv2/core.hpp #include opencv2/highgui.hpp int main() { Eigen::Matrix3d R Eigen::Matrix3d::Identity(); cv::Mat img(300, 300, CV_8UC3, cv::Scalar(0, 0, 255)); cv::imshow(ORB_SLAM2 sanity check, img); cv::waitKey(1); return 0; }这段代码如果 10 秒内编译链接全通过说明属性表生效Eigen 内存对齐也正常。如果Eigen/Dense都找不到先回上一节查 include 路径是不是指向了父目录。跑这一步的价值是把「环境变量问题」和「ORB-SLAM 代码问题」隔离别一上来就编译整个 SLAM 工程那样出错不好定位。3.3 属性表里容易忽略的两个细节.props里还有两个坑值得注意。一个是平台选择ORB-SLAM2 依赖库基本是 x64 编译的属性表若没写Platformx64/PlatformVS 默认 Win32 会把库路径找错报错是LNK2019未解析的外部符号。这时候别怀疑代码去属性管理器把平台切到 x64 再看。另一个是运行时库设置g2o、DBoW2 默认用/MD动态运行时属性表里若是/MT链接器大概率报LNK2038 mismatch。这个错的表象是_ITERATOR_DEBUG_LEVEL不匹配本质是 Debug/Release 混合以及运行库不一致。我一般直接在属性表统一设 Release /MDDebug 模式单独建一张表。这两处如果你用的包已经帮你写好就不用管但如果你是拿别人工程拼的这两个错一定会遇见。4. 跑通单目 ORB-SLAM改完路径后的一次性执行清单第三方库就位后剩下的就是把运行环境铺好。ORB-SLAM 官方代码短时间内跑不起来多数不是算法问题是路径、词典加载、图像源这些「外围活」没备好。这一章按执行顺序排避免你绕路。4.1 准备图像数据集TUM 格式最省事单目实验最常见的数据集是 TUM RGB-D 的rgbd_dataset_freiburg1_desk但纯单目跑它只需要 rgb 序列。下载解压后目录结构长这样rgbd_dataset_freiburg1_desk/ ├── rgb/ # 彩色图序列 ├── depth/ # 深度图单目不用 ├── rgb.txt # 帧名时间戳 ├── depth.txt └── groundtruth.txt # 真值轨迹评估用实际跑的时候ORB-SLAM 的mono_tum.cc会按rgb.txt逐行读取图像和时间戳。注意如果你只给rgb/文件夹而没给rgb.txt程序会直接退出报找不到文件。另外这份资源附带的 20 张张氏标定板图不是 TUM 数据集想跑完整 demo 还得自己准备一组序列图想要快速验证管线也可以用后面第 6 章说的 USB 摄像头实时模式。4.2 让工程认识系统COMPILEDWITHC11与os_specific.c在解决方案里把My_Monocular.cc设为入口文件工程类型选控制台程序链接 ORB_SLAM2 静态库。我在主工程里建议这样配置预处理器#define COMPILEDWITHC11这一行的作用是让System.cc里和std::chrono相关的代码走 C11 分支。ORB-SLAM2 老代码里还有一处usleep调用是 Unix 专用Windows 没有这个函数。资源里的os_specific.c就是干这个的它实现了usleep的 Windows 替代。如果你自己拼工程时报usleep 未定义优先检查os_specific.c是否被加进编译。顺带说一句我在 Windows 上编译完 ORB-SLAM2 后这是唯一必须要加的宏其他代码几乎不用改。4.3 一条命令跑到黑批处理脚本与绝对路径先看官方标准的运行方式ORB_SLAM2.exe ../../Vocabulary/ORBvoc.bin ../../Examples/Monocular/TUM1.yaml ../../Data/rgbd_dataset_freiburg1_desk三个参数分别对应词典路径、配置文件路径、数据集目录路径。Windows 下如果你直接复制这条命令跑多半会挂在路径上。我第一次就折在这里把数据集放在工程目录里用反斜杠写路径结果中间的\D、\r被当成了转义符路径直接失效。所以我一般写一个批处理固定住路径echo off cd /d D:\ORB_SLAM2\build D:\ORB_SLAM2\build\ORB_SLAM2.exe D:\ORB_SLAM2\Vocabulary\ORBvoc.bin D:\ORB_SLAM2\Examples\Monocular\TUM1.yaml D:\ORB_SLAM2_Data\Data\rgbd_dataset_freiburg1_desk pause这段批处理的作用是先固定工作目录再用全绝对路径启动主程序。ORBvoc.bin路径千万别写成Vocabulary\ORBvoc.bin这种相对混搭形式。右键运行后看到终端翻滚 ORB 特征点信息和帧号就说明系统活了。如果程序秒退99% 是词典路径没找到如果卡住不跑看下一帧读没读到。5. 回环检测与配置参数哪些参数属于玄学哪些有据可依ORB-SLAM2 能火很大程度靠回环检测。它基于 DBoW2 词袋模型先离线用大规模描述子训练词典ORBvoc.bin在线再把每帧的 ORB 描述子转成词袋向量。两个关键阈值是loopClosure相关参数调不好轻则不回环重则假回环。5.1 ORBvoc.bin 与 DBoW2 的加载链路程序启动时System.cc会调用Vocabulary构造函数加载ORBvoc.bin。加载过程本质是把几十万视觉词汇的层次树反序列化到内存所以启动前 1 秒会卡顿这是正常的。加载完成后每帧提取的 ORB 描述子会通过DBoW2::BowVector转成稀疏向量。这个链路在 Windows 上最常见的坑是ORBvoc.bin版本和 DBoW2 版本不匹配。比如你拿旧版包的词典去配新版 DBoW2加载不报错但回环检测永远触发不了。分辨方法是看加载后终端有没有打印Vocabulary loaded!这句没有就是版本或路径问题。5.2 单目配置里的尺度问题DepthMapFactor与ThDepth单目 SLAM 有个天然问题尺度不确定。TUM1.yaml 里Camera.fx、Camera.fy、Camera.cx、Camera.cy这几项直接决定了特征点反投影的准确性。网上很多「调参教程」告诉你把 fx 随便改这是不负责任的。正确做法是用张氏标定算出内参再填进去。这份资源附带 20 张标定板图价值就在这。Camera.fx: 517.306408 Camera.fy: 516.469215 Camera.cx: 318.643040 Camera.cy: 255.313989 ThDepth: 35.0 DepthMapFactor: 1.0这里的ThDepth对单目来说意思是「深度小于 35 倍基线才参与局部优化」。单目没有基线概念所以这个值只影响近远景区分DepthMapFactor在单目时设为 1.0 即可别去改成 1000那是 RGB-D 相机用的尺度因子。如果你把Camera.fx写错一倍地图会整体畸变回环检测照样触发但轨迹形状像哈哈镜这个错很难看出来。5.3 回环阈值与关键帧频率出厂参数一般别动DBoW2 在LoopClosing里的核心阈值是mnCovisibilityConsistencyTh和词袋向量匹配分数。官方默认对 TUM、KITTI 都调过属于「出厂参数」建议别动。真正值得你改的是KeyFrame插入策略在Tracking.cc里如果你在室内小场景掉帧严重可以把KeyFrame最小间隔从 15 降到 10代价是速度和内存上升。这类参数是「有据可依」的动它需要理由支撑不是玄学。6. Windows 下 ORB-SLAM 的四个大坑现象、原因、解决办法这一套跑通之后还有暗礁。下面四个坑我在不同机器上反复踩过每一条都按现象、原因、解决列出照着排查能省一到两天。6.1 崩溃Eigen 对齐断言assert failed现象Debug 模式下跑几十帧程序直接弹Eigen: internal eigen assertion failedRelease 正常。原因是 Eigen 的vectorization对AlignedVector3这类类型强制 16 字节对齐而 Visual Studio Debug 堆在 CRT 上默认只给 8 字节对齐。解决方法是给工程加一条编译选项/D EIGEN_DONT_VECTORIZE或者到属性表的Preprocessor Definitions里加EIGEN_DONT_VECTORIZE1。从效率角度说单目 SLAM 特征提取的耗时大头在 ORB 提取和描述子计算矩阵运算不是瓶颈关掉向量化对帧率影响很小但能根治对齐问题。6.2 链接LNK2038运行库不匹配现象链接时报LNK2038: mismatch detected for RuntimeLibrary: value MD_DynamicRelease doesnt match value MT_StaticRelease。原因是第三方库编译时用了动态运行库/MD你的工程却用了静态运行库/MT或者 Debug/Release 混合。解决是统一运行时库在属性表的C/C - Code Generation - Runtime Library里选/MD并保证你的主工程、g2o、DBoW2、OpenCV 全部是同一套。这个坑在别人给的属性表里尤其常见下载资源往往只给 Release 的表你用 Debug 编译就翻车。我的习惯是拿到包后先建一个空工程验证设置再引入 ORB-SLAM 代码。6.3 运行ORBvoc.bin加载失败但程序不退现象启动后终端打印Error opening vocabulary file但程序继续跑画面全黑或者没有特征点。原因是ORBvoc.bin路径没错但文件被截断或者该文件是文本格式的ORBvoc.txt改名而来二进制解析失败。解决是重新下载 28MB 的二进制词典文件别拿文本格式改名顶替另一个常见原因是杀毒软件把大文件锁了Windows Defender 对 28MB 的 bin 文件会做实时扫描第一次加载慢到几十秒。6.4 卡顿每帧都要重提取特征导致 CPU 满载现象帧率个位数CPU 100%但程序不崩溃。原因是 ORB-SLAM2 默认单线程提取而你用的 OpenCV 是带 IPP 的版本在某些 CPU 上 IPP 的 ORB 实现和原版 ORB 互斥。解决是设置环境变量关闭 IPP 加速set OPENCV_IPPdisabled或者代码里在main()最前面加cv::setUseOptimized(false);这个操作对 ORB-SLAM2 反而有正收益ORB-SLAM2 自带的高精度ORBextractor不走 OpenCV 的通用优化路径关掉 IPP 让它走自己的实现帧率反而稳定。如果不关表现是「偶尔快偶尔慢」这就是特征提取线程被 IPP 调度干扰的典型症状。7. 进阶技巧与二次开发从改配置到加功能跑通只是起点这份资源的真正价值是二次开发。My_Monocular.cc已把接口封装得比较干净接摄像头、换数据集、调可视化都可在这个文件里完成。7.1 把单目输入从 TUM 数据集换成 USB 摄像头TUM 数据是离线文件实时场景需要换成摄像头。My_Monocular.cc中核心改动只有几行cv::VideoCapture cap(0); // 打开默认摄像头 if (!cap.isOpened()) { cerr Failed to open camera endl; return -1; } cv::Mat im; double t 0; while (cap.read(im)) { if (im.empty()) continue; mpSystem-TrackMonocular(im, t); t 0.033; // 模拟 30Hz 时间戳 if (cv::waitKey(30) q) break; }这段代码把原来的for循环读rgb.txt的逻辑替换成while读摄像头帧TrackMonocular需要时间戳实时场景里用累计时间模拟。注意t的单位是秒必须单调递增否则局部优化器的图模型会错乱。如果摄像头画面颠倒用cv::flip(im, im, -1)在送入 SLAM 前修正。讲时间戳再展开一句ORB-SLAM2 的时间戳只用于KeyFrame插入时的相对顺序判断不参与实质的尺度恢复。所以t 0.033就算和真实帧率不符也不会让地图崩但请别用系统时钟直接填因为 Windows 的GetTickCount返回毫秒直接填会导致时间戳数值巨大日志里看不出问题但帧率和关键帧插入节奏全乱。7.2 保存相机轨迹评估误差必做的一步跑完实验不保存轨迹等于白跑。ORB-SLAM2 在System::Shutdown()后会调用SaveTrajectoryTUM但前提是你代码里显式调用。My_Monocular.cc末尾通常只有 shutdown 没有保存要自己补一行mpSystem-SaveTrajectoryTUM(trajectory.txt);SaveTrajectoryTUM输出格式是 TUM 标准timestamp tx ty tz qx qy qz qw。如果你想和groundtruth.txt对比算 ATE记得先把输出轨迹的时间戳对齐。我一般会写个小 Python 脚本做timestamp最近邻匹配再用 evo 工具算 RMSE。这样你的实验结果才有说服力评阅或验收时一张轨迹误差图能顶十句话。7.3 用附带的 20 张标定图做一次完整内参标定这部分是这份资源独有的加分项。把 20 张棋盘格图丢进 OpenCV 的标定例程可以得到相机内参和畸变参数cv::Size boardSize(9, 6); vectorvectorcv::Point3f objectPoints; vectorvectorcv::Point2f imagePoints; for (auto imgPath : imagePaths) { cv::Mat img cv::imread(imgPath); vectorcv::Point2f corners; if (cv::findChessboardCorners(img, boardSize, corners)) { // 亚像素精细化 cv::cornerSubPix(gray, corners, cv::Size(5, 5), cv::Size(-1, -1), cv::TermCriteria(cv::TermCriteria::EPS cv::TermCriteria::COUNT, 30, 0.001)); imagePoints.push_back(corners); } } cv::Mat K, distCoeffs; vectorcv::Mat rvecs, tvecs; cv::calibrateCamera(objectPoints, imagePoints, cv::Size(640, 480), K, distCoeffs, rvecs, tvecs); cout K K endl;这块代码的作用是对每张标定图找棋盘角点、做亚像素精细化、最终用calibrateCamera求出内参矩阵K。注意boardSize必须是「内角点数量」不是棋盘格数量9x6 的棋盘对应 9x6 内角点如果你数成 10x7 会报findChessboardCorners找不到角点。标定输出的K直接回填到TUM1.yaml的Camera.fx、Camera.fy等字段这比任何「网上流传的 TUM 默认参数」都靠谱。此处再提醒一个我反复踩过的顺序问题先标定再跑 SLAM别反过来。如果把 TUM 默认内参直接套在你的摄像头常见结果是地图建出来是斜的回环检测还经常误触发。先标定再填参数再跑 SLAM这个顺序我在这篇文章里强调两次并不多余。7.4 可视化与调试Pangolin 窗口黑屏怎么办ORB-SLAM2 的界面基于 PangolinWindows 下偶尔表现为窗口弹不出或全黑。现象是程序在跑终端在打帧号但 Pangolin 窗口黑屏。原因多半是 OpenGL 上下文创建失败或显卡驱动对 GLFW 不兼容。解决是在System构造时把bUseViewer参数设为false先关掉可视化跑通算法验证定位成功后再开窗口ORB_SLAM2::System::eSensor sensor ORB_SLAM2::System::MONOCULAR; mpSystem new ORB_SLAM2::System(vocPath, configPath, sensor, false);第四个参数bUseViewer传false即可。这样跑完保存轨迹到文件轨迹评估照做只是没有实时 3D 画面。如果你的目标只是课程设计或毕设的核心算法验证这一步能绕开一堆显卡驱动问题如果一定要看可视化去更新显卡驱动或者把 Pangolin 换成较新的 0.6 版本重编一次。黑屏问题在远程桌面里尤其常见远程会话启动的 OpenGL 往往只有微软的软渲染Pangolin 很容易挂掉。这件事之后我养成了一个习惯任何 ORB-SLAM 工程我都会先在代码里做一个#define USE_VIEWER 0的开关平时跑实验关掉可视化轨迹评估做完再打开窗口看效果。从那以后我在 Windows 上出图的效率高了很多希望帮到你。本文还有配套的精品资源点击获取