FAST角点检测算法原理附C++代码实现

FAST(Features from Accelerated Segment Test)角点检测算法是为实时性和高性能角点检测而设计的轻量级算法,广泛用于如 ORB、SLAM 等视觉系统中。


一、FAST 算法核心思想

FAST 不基于梯度或结构张量,而是基于像素灰度值差异在圆形邻域上的分布特征:

核心定义:

给定一个像素 p p p,以其为中心绘制一个半径为 3 的圆(16 个像素点),记为 S = { p 1 , p 2 , . . . , p 16 } S = \{p_1, p_2, ..., p_{16}\} S={p1,p2,...,p16},如下图所示。
在这里插入图片描述

  • 若在这个圆上存在连续 n n n 个像素(常用 n = 12 n = 12 n=12)满足:

    • 所有像素亮度都明显大于明显小于中心像素 p p p(与中心差值超过阈值 t t t),
  • p p p 被判定为角点,效果图如下。
    *在这里插入图片描述


二、判定过程详解

给定灰度图像像素值 I I I,对于像素 p p p

  • 阈值 t t t
  • 中心像素强度 I ( p ) I(p) I(p)

判定步骤:

  1. 定义 p p p 的圆周邻域(常用 16 点,Bresenham 圆);

  2. 若存在连续的 n n n 个邻域点 I ( p i ) I(p_i) I(pi) 满足:

    I ( p i ) > I ( p ) + t 或 I ( p i ) < I ( p ) − t I(p_i) > I(p) + t \quad \text{或} \quad I(p_i) < I(p) - t I(pi)>I(p)+tI(pi)<I(p)t

    p p p 是角点;

  3. 若未满足,则跳过。

加速策略:

  • 先测试位置 1、9、5、13 四个点(对称分布),快速排除大部分非角点;
  • 若至少三个点符合初始判定,再对 16 个点进行完整判断;
  • 可结合**非极大值抑制(NMS)**筛选局部最强响应点。

三、C++ 手动实现不依赖 OpenCV FAST API

#include <opencv2/opencv.hpp>
#include <vector>

bool isCorner(const cv::Mat& img, int x, int y, int threshold, int contiguous = 12) {
    static const int offsetX[16] = {0, 1, 2, 1, 0,-1,-2,-1,-2,-1, 0, 1, 2, 1, 0,-1};
    static const int offsetY[16] = {-3,-2, 0, 2, 3, 2, 0,-2,-1,-2,-3,-2, 0, 2, 3, 2};

    int center = img.at<uchar>(y, x);
    int brighter = 0, darker = 0;

    for (int start = 0; start < 16; ++start) {
        brighter = darker = 0;
        for (int i = 0; i < contiguous; ++i) {
            int idx = (start + i) % 16;
            int px = x + offsetX[idx];
            int py = y + offsetY[idx];
            if (px < 0 || py < 0 || px >= img.cols || py >= img.rows) continue;
            int val = img.at<uchar>(py, px);
            if (val > center + threshold) brighter++;
            else if (val < center - threshold) darker++;
            else break;
        }
        if (brighter == contiguous || darker == contiguous)
            return true;
    }
    return false;
}

std::vector<cv::Point> detectFASTCorners(const cv::Mat& gray, int threshold = 20) {
    std::vector<cv::Point> corners;
    for (int y = 3; y < gray.rows - 3; ++y) {
        for (int x = 3; x < gray.cols - 3; ++x) {
            if (isCorner(gray, x, y, threshold)) {
                corners.emplace_back(x, y);
            }
        }
    }
    return corners;
}

四、OpenCV 官方实现对比

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
    Mat gray = imread("chessboard.jpg", IMREAD_GRAYSCALE);
    Mat color;
    cvtColor(gray, color, COLOR_GRAY2BGR);

    std::vector<KeyPoint> keypoints;
    FAST(gray, keypoints, 20, true);  // 阈值20,启用非极大值抑制

    drawKeypoints(color, keypoints, color, Scalar(0, 255, 0));
    imshow("FAST Corners", color);
    waitKey(0);
    return 0;
}

五、FAST 优缺点总结

优势劣势
极快(适合实时系统)不含角点响应评分
适合图像金字塔对噪声敏感
可结合 ORB、BRIEF 特征不鲁棒于尺度和旋转变化

总结

  • FAST 基于圆邻域强度比较,利用简单、快速;
  • 判定核心是检测灰度差异连续性;
  • 可手动实现或用 OpenCV 封装;
  • 常作为 ORB 特征点的角点提取阶段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云SLAM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值