SLAM进阶——特征提取

目录

[1 现状](#1 现状)

[2 ORB算法](#2 ORB算法)

[2.1 原理](#2.1 原理)

[2.2 算法](#2.2 算法)

[2.2.1 FeatureExtraction.hpp](#2.2.1 FeatureExtraction.hpp)

[2.2.2 main.cpp](#2.2.2 main.cpp)

[2.2.3 CMakeLists.txt](#2.2.3 CMakeLists.txt)

[2.2.4 编译运行](#2.2.4 编译运行)


SLAM进阶专栏部分,系统梳理了SLAM各环节的主流算法、在具身智能与大模型中的主流使用方法,配合博主自行编写的demo进行效果展示。该专栏旨在细节了解SLAM技术在具身智能领域的主流算法、及大模型对于SLAM技术的赋能。

1 现状

在工业落地和部分实时性要求极高的场景中,特征提取ORB算法依然是主流;但在学术界、具身智能(Embodied AI)以及追求高鲁棒性的前沿方案中,ORB正在迅速被"深度学习特征"所取代。具体来说,

(1)具身智能领域

因机器人需要处理极其复杂的室内、动态、弱纹理环境(如白墙、玻璃、光影剧烈变化的厨房),目前主流趋势

a.转向深度学习描述子(Learned Descriptors)

代表算法有SuperPoint+SuperGlue/LightGlue,其在特征点匹配的准确性、光照不变性和跨视角鲁棒性上远超ORB。

b.语义与大模型结合

具身智能强调"语义导航"。现在的方案倾向于使用VLM (如 CLIP) 提取的特征或Any-point Tracking (如 TAPIR/Co-Tracker),这些算法能让机器人不仅知道"这里有个角点",还知道"这是一个杯子的边缘",从而更好地配合大模型的推理逻辑。

(2)SLAM领域

ORB-SLAM3仍然是目前工程界最鲁棒、开源生态最完整的框架。在端侧(如无人机、AR眼镜)缺乏高性能GPU的情况下,ORB凭借CPU即可跑出30-60fps的极速,具有无法撼动的地位。

前沿:

a.Neural SLAM与Dense SLAM

使用Gaussian Splatting (3DGS) 或NeRF作为后端(如 GS-SLAM),这类方案通常不再使用传统的ORB特征提取,而是直接利用像素级信息或全连接的神经特征。

b.混合式SLAM

保留SLAM 后端(位姿图优化/BA),但将前端换成LoFTR(无须特征点的匹配)或 DKN。

(3)大模型领域

因大模型需要全局上下文信息,ORB丢失了太多的语义和颜色一致性。大模型+视觉定位方面已经彻底抛弃局部特征,主流趋势 是Topometric Navigation(拓扑度量导航),即利用大模型的视觉编码器将场景编码为向量空间,通过向量搜索实现"重定位",而不是靠匹配ORB的二进制描述子。主流算法是使用DINOv2或CLIP提取的密集特征(Dense Features)。

2 ORB算法

2.1 原理

Oriented FAST特征点检测 + BRIEF描述子生成。 Oriented FAST算法包括FAST算法、尺度不变性(金字塔)、旋转一致性。FAST算法 通过检查像素点周围的一个圆周(通常是 16 个像素)来判断。如果圆周上有连续多个像素点的亮度显著高于或低于中心点,则判定为特征点。它的特点是极快;尺度不变性 指ORB对原始图像构建"图像金字塔"(不断缩小的图像层级),在每一层都检测一遍特征点,这样无论物体在远还是在近,都能被捕捉到;旋转一致性指ORB通过计算特征点邻域内的质心 (Intensity Centroid),从中心指向质心的向量即为该特征点的"方向",这使得算法在图像旋转时依然能匹配上。

算法细节详见:7.1,https://blog.csdn.net/weixin_45728280/article/details/148474199

2.2 算法

创建demo文件夹,创建FeatureExtraction文件夹,打开VS Code。

2.2.1 FeatureExtraction.hpp
cpp 复制代码
#include <iostream>
#include <vector>
#include <cassert>
#include <opencv2/opencv.hpp>
#include <chrono>

class FeatureTracker
{
public:
    // 构造n函数,初始化探测器
    FeatureTracker(int n_features = 500) 
    {
        orb_ = cv::ORB::create(n_features);
        std::cout << "[LOG] FeatureTracker Initialized with " << n_features << " features." << std::endl;
    }

    // 核心功能,处理图像
    void processImage(const std::string& path, int frame_id) 
    {
        // 1.读取图像
        cv::Mat img = cv::imread(path, cv::IMREAD_COLOR);
        // 2.检查图像是否成功加载
        assert(!img.empty() && "Image not found or unable to open");
        // 计时
        auto t1 = std::chrono::steady_clock::now();
        // 3.特征提取
        std::vector<cv::KeyPoint> keypoints;
        cv::Mat descriptors;
        orb_->detectAndCompute(img, cv::noArray(), keypoints, descriptors);
        // 计时结束
        auto t2 = std::chrono::steady_clock::now();
        auto time_used = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
        std::cout << "[LOG] Processing time: " << time_used << " ms, Keypoints detected: " << keypoints.size() << std::endl;
        // 4.可视化特征点
        cv::Mat img_out;
        cv::drawKeypoints(img, keypoints, img_out, cv::Scalar(0, 255, 0));
        // 5.显示结果
        cv::imshow("Feature Points", img_out);
        // // 6.保存文件
        // std::string save_name = std::to_string(frame_id) + "_.png";
        // for (size_t i = 0; i < 10; ++i) 
        //   cv::imwrite(save_name, img_out);
    }
private:
    // 使用智能指针管理OpenCV对象
    cv::Ptr<cv::ORB> orb_;
};
2.2.2 main.cpp
cpp 复制代码
#include <iostream>
#include <vector>
#include "FeatureTracking.hpp"
#include <opencv2/opencv.hpp>
#include <string>

int main(int argc, char** argv) 
{
    // 检查命令行参数
    if (argc != 2) 
    {
        std::cerr << "Usage: ./feature_demo <path_to_image>" << std::endl;
        return -1;
    }

    // 导入图像路径
    std::string image_path = argv[1];
    std::vector<cv::String> image_files;
    cv::glob(image_path + "/*.png", image_files);

    if (image_files.empty())
    {
        std::cerr << "No images found in the specified directory." << std::endl;
        return -1;
    }
    std::cout << "[LOG] Found " << image_files.size() << " images." << std::endl;
    
    // 初始化追踪器
    FeatureTracker tracker(1000); // 初始化时设置特征点数量为1000
    // 处理每一张图像
    for (size_t i = 0; i < image_files.size(); ++i) 
    {
        tracker.processImage(image_files[i], i);
        if (cv::waitKey(30) == 'q') break; // 按任意键退出
    }
    cv::destroyAllWindows();
    std::cout << "[LOG] Processing completed." << std::endl;
    return 0;
}
2.2.3 CMakeLists.txt
cpp 复制代码
cmake_minimum_required(VERSION 3.10)
project(FeatureDemo)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 14)

# 1. 寻找 OpenCV 库
find_package(OpenCV REQUIRED)

# 2. 指定头文件路径
include_directories(${OpenCV_INCLUDE_DIRS})

# 3. 生成可执行文件
add_executable(feature_demo main.cpp) 

# 4. 链接 OpenCV 库
target_link_libraries(feature_demo ${OpenCV_LIBS})
2.2.4 编译运行
cpp 复制代码
cd ~/demo/FeatureExtraction
mkdir build
cmake ..
make -j$(nproc)

打开build文件,创建results文件,

运行:

cpp 复制代码
./feature_demo +数据集所在文件夹路径

PS.数据集所在文件夹路径可直接将目标图片拖入终端,然后删除该图片名称。

相关推荐
这张生成的图像能检测吗1 天前
(论文速读)Unified Modality Separation: 无监督领域自适应的视觉语言框架
人工智能·机器学习·无监督学习·视觉语言模型·域自适应·跨模态融合·模态差异
Hcoco_me1 天前
大模型面试题30:Padding 的 mask 操作
人工智能·rnn·深度学习·lstm·word2vec
2401_841495641 天前
【机器学习】深度信念网络(DBN)
人工智能·python·深度学习·神经网络·机器学习·无监督预训练·有监督微调
hay_lee1 天前
DeepSeek开年发布新论文:提出新型残差连接mHC
人工智能·算法·机器学习·deepseek·mhc
Jerryhut1 天前
Opencv总结6——sift算法
人工智能·opencv·算法
schinber1 天前
什么是Bert?
人工智能·自然语言处理·bert
小oo呆1 天前
【自然语言处理】提示词编写指南
人工智能·自然语言处理
Hcoco_me1 天前
大模型面试题33:Transformer为什么用LayerNorm,而非BatchNorm?
人工智能·rnn·深度学习·自然语言处理·transformer·word2vec
软件不硬1 天前
从人工智能到大语言模型
人工智能·语言模型·自然语言处理