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


一、FAST 算法核心思想

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

核心定义:

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

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

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


二、判定过程详解

给定灰度图像像素值 III,对于像素 ppp

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

判定步骤:

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

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

    I(pi)>I(p)+t或I(pi)<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

    ppp 是角点;

  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 特征点的角点提取阶段。
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐