FAST角点检测算法原理附C++代码实现
给定一个像素ppp,以其为中心绘制一个半径为 3 的圆(16 个像素点),记为Sp1p2p16Sp1p2...p16,如下图所示。若在这个圆上存在连续nnn个像素(常用n12n = 12n12所有像素亮度都明显大于或明显小于中心像素ppp(与中心差值超过阈值ttt),则ppp被判定为角点,效果图如下。优势劣势极快(适合实时系统)不含角点响应评分适合图像金字塔对噪声敏感可结合 ORB、BRIE
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)
判定步骤:
-
定义 ppp 的圆周邻域(常用 16 点,Bresenham 圆);
-
若存在连续的 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)+t或I(pi)<I(p)−t
则 ppp 是角点;
-
若未满足,则跳过。
加速策略:
- 先测试位置 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 特征点的角点提取阶段。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)