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)
判定步骤:
-
定义 p p p 的圆周邻域(常用 16 点,Bresenham 圆);
-
若存在连续的 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)+t或I(pi)<I(p)−t
则 p p p 是角点;
-
若未满足,则跳过。
加速策略:
- 先测试位置 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 特征点的角点提取阶段。