1. GCNv2_SLAM环境搭建与问题排查最近在Ubuntu 18.04上部署GCNv2_SLAM时遇到了不少坑。这里分享下我的实战经验特别是针对高版本libtorch的适配问题。首先需要明确的是GCNv2_SLAM这个项目最初是基于PyTorch 1.3开发的而现在主流环境都已经升级到更高版本这就导致直接编译会遇到各种兼容性问题。我的测试环境配置如下操作系统Ubuntu 18.04 LTS编译器g 7.5.0CUDA版本11.1libtorch版本1.9.1cu111安装依赖时要注意除了基本的OpenCV、Eigen3等库外最关键的是要确保libtorch版本与CUDA版本匹配。我建议直接从PyTorch官网下载预编译好的libtorch包这样可以避免很多不必要的麻烦。下载后解压到指定目录记得设置好环境变量export Torch_DIR/path/to/libtorch/share/cmake/Torch编译过程中最常见的错误就是ABI兼容性问题。这是因为新版本的libtorch默认使用C11 ABI而老版本项目可能使用的是pre-C11 ABI。解决方法是在CMakeLists.txt中显式设置C标准set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON)2. 源码适配与关键修改点拿到GCNv2_SLAM源码后第一件事就是检查代码中与PyTorch相关的部分。由于PyTorch的API在1.3到1.9之间发生了不少变化这里有几个关键修改点需要注意。在GCNextractor.h文件中原来的模块指针定义需要修改// 原代码 std::shared_ptrtorch::jit::script::Module module; // 修改后 torch::jit::script::Module module;对应的前向传播调用也要调整// 原代码 auto output module-forward(inputs).toTuple(); // 修改后 auto output module.forward(inputs).toTuple();模型文件(.pt)也需要进行适配。用文本编辑器打开gcn2_320x240.pt文件找到gcn.py部分修改以下两处# 原代码 _32 torch.squeeze(torch.grid_sampler(input, grid, 0, 0)) # 修改后 _32 torch.squeeze(torch.grid_sampler(input, grid, 0, 0, True)) # 原代码 _14 torch.unsqueeze(torch.index(det, [_12, _13]), 1) # 修改后 det_flatten torch.flatten(det, start_dim0, end_dim-1) _12_13 _12*320_13 _14 torch.unsqueeze(torch.index_select(det_flatten, 0, _12_13),1)这些修改主要是为了适配PyTorch API的变化特别是index操作在新版本中的行为发生了改变。我花了整整两天时间才定位到这些问题希望这些经验能帮你节省时间。3. 特征匹配验证方案设计为了验证修改后的GCNv2特征提取器是否正常工作我设计了一个独立的双目特征匹配测试程序。这个方案有几个优点可以快速验证特征提取效果不需要依赖完整的SLAM系统可视化结果直观明了测试程序的主要流程如下读取左右目图像分别用GCNv2提取特征点和描述子使用暴力匹配器(BFMatcher)进行特征匹配筛选优质匹配点可视化匹配结果关键代码结构如下GCNextractor* leftExtractor new GCNextractor(1000,1.2,8,20,7); GCNextractor* rightExtractor new GCNextractor(1000,1.2,8,20,7); std::vectorcv::KeyPoint leftKeys, rightKeys; cv::Mat leftDescriptors, rightDescriptors; (*leftExtractor)(leftImage, cv::Mat(), leftKeys, leftDescriptors); (*rightExtractor)(rightImage, cv::Mat(), rightKeys, rightDescriptors); cv::BFMatcher matcher(cv::NORM_HAMMING); std::vectorcv::DMatch matches; matcher.match(leftDescriptors, rightDescriptors, matches);匹配结果筛选采用了经典的最短距离倍数法double minDist 1000; for(auto m : matches) { if(m.distance minDist) minDist m.distance; } std::vectorcv::DMatch goodMatches; for(auto m : matches) { if(m.distance max(1.2*minDist, 30.0)) { goodMatches.push_back(m); } }4. 实验结果分析与优化建议经过多次测试我发现GCNv2在特征提取方面有几个特点值得注意尺度不变性相比传统ORB特征GCNv2对图像缩放表现出更好的鲁棒性。在测试中即使将图像缩小到80%仍能保持较高的匹配成功率。旋转敏感性当相机旋转角度较大时(30度)匹配准确率会明显下降。这与论文中的结论一致说明GCNv2的旋转不变性还有提升空间。计算效率在GTX 1080Ti上处理320x240图像的平均耗时约为15ms基本能满足实时性要求。但如果图像分辨率提高到640x480耗时将增加到40ms左右。针对这些观察我总结了几个优化建议分辨率选择320x240是一个比较好的折中点既能保证特征质量又能满足实时性要求。特征点数量默认的1000个特征点可能过多实际测试发现500-800个点已经足够而且能显著降低计算负担。匹配策略可以考虑加入双向匹配筛选进一步提高匹配准确率std::vectorcv::DMatch forwardMatches, backwardMatches; matcher.match(leftDescriptors, rightDescriptors, forwardMatches); matcher.match(rightDescriptors, leftDescriptors, backwardMatches); std::vectorcv::DMatch goodMatches; for(auto fm : forwardMatches) { for(auto bm : backwardMatches) { if(fm.queryIdx bm.trainIdx fm.trainIdx bm.queryIdx) { goodMatches.push_back(fm); break; } } }从实际效果来看GCNv2的特征确实比传统ORB特征更具区分度特别是在纹理较弱的区域。不过也存在一些误匹配的情况这需要在后续的SLAM集成中通过几何约束进一步筛选。
GCNv2_SLAM实战:从源码适配到特征匹配验证
1. GCNv2_SLAM环境搭建与问题排查最近在Ubuntu 18.04上部署GCNv2_SLAM时遇到了不少坑。这里分享下我的实战经验特别是针对高版本libtorch的适配问题。首先需要明确的是GCNv2_SLAM这个项目最初是基于PyTorch 1.3开发的而现在主流环境都已经升级到更高版本这就导致直接编译会遇到各种兼容性问题。我的测试环境配置如下操作系统Ubuntu 18.04 LTS编译器g 7.5.0CUDA版本11.1libtorch版本1.9.1cu111安装依赖时要注意除了基本的OpenCV、Eigen3等库外最关键的是要确保libtorch版本与CUDA版本匹配。我建议直接从PyTorch官网下载预编译好的libtorch包这样可以避免很多不必要的麻烦。下载后解压到指定目录记得设置好环境变量export Torch_DIR/path/to/libtorch/share/cmake/Torch编译过程中最常见的错误就是ABI兼容性问题。这是因为新版本的libtorch默认使用C11 ABI而老版本项目可能使用的是pre-C11 ABI。解决方法是在CMakeLists.txt中显式设置C标准set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON)2. 源码适配与关键修改点拿到GCNv2_SLAM源码后第一件事就是检查代码中与PyTorch相关的部分。由于PyTorch的API在1.3到1.9之间发生了不少变化这里有几个关键修改点需要注意。在GCNextractor.h文件中原来的模块指针定义需要修改// 原代码 std::shared_ptrtorch::jit::script::Module module; // 修改后 torch::jit::script::Module module;对应的前向传播调用也要调整// 原代码 auto output module-forward(inputs).toTuple(); // 修改后 auto output module.forward(inputs).toTuple();模型文件(.pt)也需要进行适配。用文本编辑器打开gcn2_320x240.pt文件找到gcn.py部分修改以下两处# 原代码 _32 torch.squeeze(torch.grid_sampler(input, grid, 0, 0)) # 修改后 _32 torch.squeeze(torch.grid_sampler(input, grid, 0, 0, True)) # 原代码 _14 torch.unsqueeze(torch.index(det, [_12, _13]), 1) # 修改后 det_flatten torch.flatten(det, start_dim0, end_dim-1) _12_13 _12*320_13 _14 torch.unsqueeze(torch.index_select(det_flatten, 0, _12_13),1)这些修改主要是为了适配PyTorch API的变化特别是index操作在新版本中的行为发生了改变。我花了整整两天时间才定位到这些问题希望这些经验能帮你节省时间。3. 特征匹配验证方案设计为了验证修改后的GCNv2特征提取器是否正常工作我设计了一个独立的双目特征匹配测试程序。这个方案有几个优点可以快速验证特征提取效果不需要依赖完整的SLAM系统可视化结果直观明了测试程序的主要流程如下读取左右目图像分别用GCNv2提取特征点和描述子使用暴力匹配器(BFMatcher)进行特征匹配筛选优质匹配点可视化匹配结果关键代码结构如下GCNextractor* leftExtractor new GCNextractor(1000,1.2,8,20,7); GCNextractor* rightExtractor new GCNextractor(1000,1.2,8,20,7); std::vectorcv::KeyPoint leftKeys, rightKeys; cv::Mat leftDescriptors, rightDescriptors; (*leftExtractor)(leftImage, cv::Mat(), leftKeys, leftDescriptors); (*rightExtractor)(rightImage, cv::Mat(), rightKeys, rightDescriptors); cv::BFMatcher matcher(cv::NORM_HAMMING); std::vectorcv::DMatch matches; matcher.match(leftDescriptors, rightDescriptors, matches);匹配结果筛选采用了经典的最短距离倍数法double minDist 1000; for(auto m : matches) { if(m.distance minDist) minDist m.distance; } std::vectorcv::DMatch goodMatches; for(auto m : matches) { if(m.distance max(1.2*minDist, 30.0)) { goodMatches.push_back(m); } }4. 实验结果分析与优化建议经过多次测试我发现GCNv2在特征提取方面有几个特点值得注意尺度不变性相比传统ORB特征GCNv2对图像缩放表现出更好的鲁棒性。在测试中即使将图像缩小到80%仍能保持较高的匹配成功率。旋转敏感性当相机旋转角度较大时(30度)匹配准确率会明显下降。这与论文中的结论一致说明GCNv2的旋转不变性还有提升空间。计算效率在GTX 1080Ti上处理320x240图像的平均耗时约为15ms基本能满足实时性要求。但如果图像分辨率提高到640x480耗时将增加到40ms左右。针对这些观察我总结了几个优化建议分辨率选择320x240是一个比较好的折中点既能保证特征质量又能满足实时性要求。特征点数量默认的1000个特征点可能过多实际测试发现500-800个点已经足够而且能显著降低计算负担。匹配策略可以考虑加入双向匹配筛选进一步提高匹配准确率std::vectorcv::DMatch forwardMatches, backwardMatches; matcher.match(leftDescriptors, rightDescriptors, forwardMatches); matcher.match(rightDescriptors, leftDescriptors, backwardMatches); std::vectorcv::DMatch goodMatches; for(auto fm : forwardMatches) { for(auto bm : backwardMatches) { if(fm.queryIdx bm.trainIdx fm.trainIdx bm.queryIdx) { goodMatches.push_back(fm); break; } } }从实际效果来看GCNv2的特征确实比传统ORB特征更具区分度特别是在纹理较弱的区域。不过也存在一些误匹配的情况这需要在后续的SLAM集成中通过几何约束进一步筛选。