当前位置: 首页 > news >正文

AKAZE(Accelerated-KAZE)图像特征点检测算法详解和C++代码实现示例

AKAZE(Accelerated-KAZE)是一种高效的图像局部特征提取算法,于 2013 年由 Pablo Fernández Alcantarilla 等人提出,其目的是在保持 KAZE 特征优异性能的同时显著加速特征提取过程。AKAZE 属于尺度不变特征检测与描述的算法,其在非线性尺度空间中寻找关键点,并使用特有的二值描述符加速匹配过程,广泛应用于图像配准、SLAM 和图像检索等领域。


一、背景与发展

  • SIFT(2004):提出了基于高斯金字塔的尺度空间概念,奠定了特征检测与描述的理论基础。

  • SURF(2006):引入积分图像以加速计算,提出 Hessian-based 特征检测器。

  • KAZE(2012):首次引入**非线性扩散滤波(Nonlinear Diffusion Filtering)**构建尺度空间,使得特征更好地保留图像边缘与结构信息。

    • 缺点:KAZE 特征虽稳定,但计算量大,速度慢。
  • AKAZE(2013):优化 KAZE,通过 加速的近似非线性扩散方法(Fast Explicit Diffusion, FED) 构建尺度空间,并提出 M-LDB(二进制描述符),大幅提升速度,适用于实时系统。


二、AKAZE 算法原理概述

AKAZE 是在 KAZE 特征算法基础上,将 非线性扩散尺度空间与 **M-LDB(二值描述子)**结合,采用 Fast Explicit Diffusion (FED) 加速非线性扩散结构,同时保持尺度与旋转不变性,并实现高效匹配 。

核心流程:

  1. 构建非线性尺度空间(diffusion-based scale space)
  2. 在尺度空间中检测极值点(using Hessian determinant)
  3. 插值定位关键点(亚像素位置与尺度)
  4. 估计主方向(基于梯度积分/质心等法)
  5. 使用 M-LDB 描述子对关键点进行编码(rotation+scale invariant binary)
  6. 输出关键点与描述子

三、非线性尺度空间与 FED 推导

非线性尺度空间模型基于如下扩散 PDE:

∂ L ∂ t = ∇ ⋅ ( c ( ∥ ∇ L ∥ ) ∇ L ) , L ( x , 0 ) = I ( x ) \frac{\partial L}{\partial t} = \nabla \cdot \left( c(\|\nabla L\|) \nabla L \right), \quad L(x,0) = I(x) tL=(c(∥∇L)L),L(x,0)=I(x)

其中 c ( ) c() c() 是依赖于梯度强度的导热系数,用于平滑噪声同时保护边缘 ([projet.liris.cnrs.fr][1], [researchgate.net][3])。AKAZE 利用 FED(Fast Explicit Diffusion)离散化技术:

L ( k + 1 ) = L ( k ) + τ k A ( L ( k ) ) L^{(k+1)} = L^{(k)} + \tau_k A(L^{(k)}) L(k+1)=L(k)+τkA(L(k))

通过预计算不同 τ k \tau_k τk 部分构建时间膨胀(scale levels)。尺度与时间成比例关系。


四、关键点检测:Hessian 极值

在多尺度空间中,用 Hessian 行列式做特征检测:

H = [ L x x L x y L x y L y y ] , det ⁡ ( H ) = L x x L y y − L x y 2 H = \begin{bmatrix} L_{xx} & L_{xy} \\ L_{xy} & L_{yy} \end{bmatrix}, \quad \det(H) = L_{xx}L_{yy} - L_{xy}^2 H=[LxxLxyLxyLyy],det(H)=LxxLyyLxy2

在各尺度住房中检测极值点,只保留 det ⁡ ( H ) > \det(H) > det(H)> 阈值的特征点,类似 SIFT DoG 或 KAZE 检测 ([projet.liris.cnrs.fr][1], [researchgate.net][3])。


五、主方向与 M-LDB 描述子

方向估计(orientation)

利用非线性尺度空间图像梯度:

  • 在关键点邻域内采样梯度向量(dx, dy)
  • 使用旋转窗口(如固定圆)或可选质心法估计主方向

M-LDB(二值描述子)

基于灰度差异统计,分块计算:

  • 每个子区域(如 4×4),提取平均 dx, dy 和绝对值
  • 将方向一致性编码为二值,构成 11×11 或 6×6 子块描述
  • 总术生成 64/128bit,例如 uint64_t[2],支持快速 Hamming 距计算 ([projet.liris.cnrs.fr][1], [diva-portal.org][4])

六、纯 C++ 实现结构示例

大家可以按如下结构实现 AKAZE:

class AKAZE {
public:AKAZE(const Image& I, ...params...);void detectKeypoints(vector<Keypoint>& kpts);void computeDescriptors(vector<Keypoint>& kpts, vector<Descriptor>& descs);
};struct Keypoint {float x, y, scale;float response;float angle;
};typedef array<uint64_t,2> Descriptor; // 128-bit mask

核心模块:

  • buildScaleSpace():使用 FED 构造一组响应图
  • detect():扫描极值点并进行插值细化
  • computeOrientation():投票窗口或质心法
  • computeMLDB():分块采样 + 二值测试

可参考纯 C++ 实现 akaze-eigen,结构与原始 OpenCV 源代码保持一致 。


七、AKAZE 与其他算法对比

特征算法尺度不变旋转不变描述子类型特点
SIFT浮点128D高鲁棒,慢
SURF浮点64D快,牺牲精度
ORB部分二值256bit快,低复杂度
AKAZE二值128bit平衡鲁棒与性能
DOME二值更轻量,但鲁棒性一般

八、总结

  • AKAZE 使用非线性扩散尺度空间 + FED 加速,保留边缘信息;
  • 检测 Hessian 极值,计算主方向后生成 M-LDB 二值描述;
  • 适合资源较紧但需要尺度/旋转不变的场景。

九、非线性尺度空间构建和M-LDB 描述子构建详解C++实现

1. buildScaleSpace() 非线性尺度空间构建

AKAZE 使用 非线性扩散 PDE 模型,借助 FED(Fast Explicit Diffusion) 方法近似求解:

PDE 模型

∂ L ∂ t = ∇ ⋅ ( c ( ∥ ∇ L ∥ ) ∇ L ) , L ( x , 0 ) = I ( x ) \frac{\partial L}{\partial t} = \nabla \cdot \left( c(\|\nabla L\|) \nabla L \right), \quad L(x,0) = I(x) tL=(c(∥∇L)L),L(x,0)=I(x)

其中:

  • L L L 是图像(随时间演化)
  • c ( ∥ ∇ L ∥ ) c(\|\nabla L\|) c(∥∇L) 是导热函数(控制扩散速度)
  • t t t 是“时间尺度”,可类比高斯金字塔的 σ²

常见导热函数形式(Perona-Malik)

c ( s ) = exp ⁡ ( − ( s κ ) 2 ) 或 c ( s ) = 1 1 + ( s κ ) 2 c(s) = \exp\left( -\left(\frac{s}{\kappa}\right)^2 \right) \quad \text{或} \quad c(s) = \frac{1}{1 + \left(\frac{s}{\kappa}\right)^2} c(s)=exp((κs)2)c(s)=1+(κs)21

其中 κ \kappa κ 控制边缘敏感性,s 是梯度幅值 s = ∥ ∇ L ∥ s = \|\nabla L\| s=∥∇L


FED 离散化公式

每一层尺度 L i L_i Li 使用 FED 离散时间步:

L t + Δ t k = L t + Δ t k ⋅ ∇ ⋅ ( c ( ∥ ∇ L ∥ ) ∇ L ) L_{t+\Delta t_k} = L_t + \Delta t_k \cdot \nabla \cdot \left( c(\|\nabla L\|) \nabla L \right) Lt+Δtk=Lt+Δtk(c(∥∇L)L)

用离散卷积方式表示为:

// 对于图像 L,应用 explicit diffusion step:
L_next = L + dt_k * divergence(c * gradient(L));

FED 通过控制 Δ t k \Delta t_k Δtk(非均匀),近似多尺度演化:

Δ t k = τ ⋅ sin ⁡ 2 ( π ( k + 1 ) 2 n + 2 ) , k = 0 … n − 1 \Delta t_k = \tau \cdot \sin^2\left( \frac{\pi(k+1)}{2n+2} \right), \quad k = 0 \ldots n-1 Δtk=τsin2(2n+2π(k+1)),k=0n1

FED 优点:允许使用较大时间步 Δ t k \Delta t_k Δtk 保持稳定性,提升速度。


尺度构建结构
struct NonlinearScaleLevel {Image img;        // 演化后的图像float sigma;      // 尺度float timestep;   // t
};std::vector<NonlinearScaleLevel> buildScaleSpace(const Image& input) {std::vector<NonlinearScaleLevel> levels;Image current = input;for (int octave = 0; octave < num_octaves; ++octave) {for (int sublevel = 0; sublevel < sublevels; ++sublevel) {float sigma = computeSigma(octave, sublevel);Image diffused = applyFED(current, sigma, num_steps);levels.push_back({diffused, sigma});}current = downsample(current);}return levels;
}

2. M-LDB 描述子构建核心逻辑

概要

M-LDB(Modified Local Difference Binary)是基于:

  • 分块平均灰度/梯度方向值
  • 对比成对子块间特征值(类似 BRIEF,但更加稳定)
  • 输出 64-bit 或 128-bit 描述符

步骤 1:旋转+尺度采样区域提取

假设 keypoint K = ( x , y , θ , σ ) K = (x, y, \theta, \sigma) K=(x,y,θ,σ),提取旋转对齐的 patch:

// 提取旋转 patch 并计算平均值
float cosT = cos(kp.angle);
float sinT = sin(kp.angle);
for (int i = 0; i < n_cells; ++i)for (int j = 0; j < n_cells; ++j)// compute rotated cell center: (dx, dy)// sample intensities or gradient features

步骤 2:每个子块提取统计特征

对于每个 cell:

  • 计算:

    • 灰度均值 μ \mu μ
    • d x , d y dx, dy dx,dy 平均梯度
    • 梯度幅值 ∣ g ∣ |g| g
struct CellFeature {float mean_intensity;float mean_dx;float mean_dy;
};

步骤 3:构造二值对比特征

对所有 cell 间成对比较(如下):

bit k = { 1 , if  f i > f j 0 , otherwise \text{bit}_k = \begin{cases} 1, & \text{if } f_i > f_j \\ 0, & \text{otherwise} \end{cases} bitk={1,0,if fi>fjotherwise

对比特征示例:

  • μ i > μ j \mu_i > \mu_j μi>μj
  • ∣ g i ∣ > ∣ g j ∣ |g_i| > |g_j| gi>gj
  • d x i > d x j dx_i > dx_j dxi>dxj

最后将所有位拼接成描述子,例如 uint64_t[2](128bit):

uint64_t desc[2] = {0};
int bit_idx = 0;
for (int i = 0; i < N; ++i)for (int j = i+1; j < N; ++j) {if (features[i].mean_intensity > features[j].mean_intensity)set_bit(desc, bit_idx);bit_idx++;// same for dx, dy, magnitude ...}

3、小结

模块内容
尺度空间构建FED 显式扩散 + Perona-Malik 导热函数
特征检测多尺度 Hessian 行列式极值
主方向估计旋转对齐梯度/投票
M-LDB 描述子分块均值、梯度 → 二值比较 → 生成位图

十、参考文献

  • Alcantarilla, P. F., Bartoli, A., & Davison, A. J. (2013). “Fast explicit diffusion for accelerated features in nonlinear scale spaces”, BMVC 2013.
  • Alcantarilla, P. F., Nuevo, J., & Bartoli, A. (2013). AKAZE features, https://github.com/pablofdezalc/akaze

http://www.dtcms.com/a/264280.html

相关文章:

  • 6.2 实现文档加载和切分和简易向量数据库的功能
  • 【在 FastAdmin 中取消特定字段的搜索功能】
  • Conda 虚拟环境克隆与 PyCharm 配置教程
  • 高阶数据结构------并查集
  • uniapp+vue3 中使用echart 以及echart文件过大需要分包的记录
  • 吸烟行为检测数据集介绍-2,108张图片 公共场所禁烟监控 健康行为研究
  • SpringCloud系列(45)--SpringCloud Bus简介
  • UE5 - 制作《塞尔达传说》中林克的技能 - 18 - 磁力抓取器
  • 强化学习【chapter0】-学习路线图
  • Java Selenium反爬虫技术方案
  • 07 Springboot+netty+mqtt服务端实现【重构】
  • 数据结构之带头双向循环链表
  • 苍穹外卖系列问题之Day11_05营业额统计代码开发2 StringUtils.join(dateList,“,“)报错
  • Cross-modal Information Flow in Multimodal Large Language Models
  • 【1.6 漫画数据库设计实战 - 从零开始设计高性能数据库】
  • 2025年主流大厂Java后端面试题主题深度解析
  • 推客系统小程序终极指南:从0到1构建自动裂变增长引擎,实现业绩10倍增长!
  • 快速手搓一个MCP服务指南(九): FastMCP 服务器组合技术:构建模块化AI应用的终极方案
  • 【大模型学习 | BLIP2原理】
  • 「Java流程控制」for循环结构
  • langchain从入门到精通(三十二)——RAG优化策略(八)自查询检索器实现动态数据过滤
  • 腾讯 iOA 零信任产品:安全远程访问的革新者
  • Redis-渐进式遍历
  • Java后端调用外部接口标准流程详解
  • python+uniapp基于微信小程序的PS社区系统
  • 使用D435i运行ORB-SLAM3时,纯视觉模式与视觉-惯性模式的位姿矩阵定义问题探讨
  • 基于SpringBoot + HTML 的网上书店系统
  • 转录组分析流程(六):列线图
  • Kafka 生产者和消费者高级用法
  • c++学习(八、函数指针和线程)