xFfast7x7函数
这个代码是7X7的窗口的FAST角点检测。Template的定义和前面几个函数的一致,可以看之前的解释,这边不再展开。
void xFfast7x7(hls::stream<ap_uint<8> > &_src_mat,
hls::stream< ap_uint<16> > &_out_mat, ap_uint<8> win_size,
uint16_t img_height, uint16_t img_width,uchar_t _threshold)
输入:_src_mat 是 8 位无符号整数流(hls::stream是 HLS 专用的流接口,适合连续数据传输),存储原始图像像素(如灰度值);
输出:_out_mat 是 16 位无符号整数流,存储处理结果(结合前文,可能是特征值与中心像素的组合数据);
配置参数:win_size(窗口实际尺寸)、img_height/img_width(图像高 / 宽)、_threshold(特征检测的阈值,如 FAST 角点的亮度差阈值)
row_ind 是存储滑动窗口内各位置对应原始图像行索引的数组:ap_uint<13> 为 13 位无符号硬件友好型数据类型(适配图像行索引范围,通常不超过 8192),数组大小为窗口尺寸 WIN_SZ(如 7x7 窗口则为 7),用于快速映射窗口内每个位置(0~WIN_SZ-1)对应的原始图像行坐标(避免重复计算)
XF_PTNAME(DEPTH) pack_corners;
用于存储角点信息。
XF_PTNAME(DEPTH) 是 Xilinx 图像加速库(XF 库)的宏,用于根据图像数据深度 DEPTH(如 8 位、16 位)自动匹配对应的像素 / 数据类型(例如 8 位深度时可能为 unsigned char)。
pack_corners 用于存储 “打包后的角点信息”:在 FAST 角点检测中,检测到的角点坐标或状态需要按一定格式打包(便于硬件高效传输或存储),该变量承担这一角色。
uint16_t shift_x = 0;
ap_uint<13> row, col;
unsigned char OutputValues[XF_NPIXPERCYCLE(NPC)];
#pragma HLS ARRAY_PARTITION variable=OutputValues complete dim=1
shift_x 是 16 位无符号整数,初始化为 0,代表水平方向的偏移量。在滑动窗口处理中,常用于校准窗口在水平方向的起始位置(例如窗口步长不为 1 时,记录累计偏移以确保窗口对齐),或在并行处理多像素时同步数据位置,避免因并行读写导致的位置偏差。
ap_uint<13> 是 Xilinx HLS 专用的 “13 位无符号整数类型”,选择 13 位是因为图像的行列索引范围通常不超过 8192(2¹³=8192),既能覆盖绝大多数图像尺寸(如常见的 4096x4096 以内),又比 32 位整数更节省硬件资源(寄存器 / 存储单元),适合硬件实现。
row 和 col 分别表示当前正在处理的像素的行索引和列索引,用于跟踪滑动窗口在图像中的位置,是遍历图像、判断边界(如是否超出图像高 / 宽)的核心变量。
XF_NPIXPERCYCLE(NPC) 是 Xilinx 图像加速库(XF 库)的宏,根据 “像素并行度”NPC(如 XF_NPPC8 表示 8 像素并行处理)计算每周期处理的像素数量(例如 NPC=8 时,数组大小为 8)。
OutputValues 是存储特征检测结果的数组,类型为 unsigned char(8 位),适合存储 0-255 范围内的特征值(如 FAST 角点的响应强度、是否为角点的标志等),数组大小与并行处理的像素数匹配,确保每周期的所有结果都能被存储。
unsigned char src_buf[WIN_SZ][XF_NPIXPERCYCLE(NPC)+(WIN_SZ-1)];
#pragma HLS ARRAY_PARTITION variable=src_buf complete dim=1
#pragma HLS ARRAY_PARTITION variable=src_buf complete dim=2
// src_buf1 et al merged
XF_SNAME(WORDWIDTH) P0;
第一维 WIN_SZ:对应滑动窗口的行数(如 7x7 窗口的 WIN_SZ=7),即缓冲区有 WIN_SZ 行,每行存储窗口中一行的像素数据。
第二维 XF_NPIXPERCYCLE(NPC) + (WIN_SZ-1):由两部分组成:
XF_NPIXPERCYCLE(NPC):Xilinx XF 库宏,根据像素并行度 NPC(如 XF_NPPC8 表示 8 像素并行)计算每周期处理的像素数(例如 NPC=8 时,该值为 8);
(WIN_SZ-1):补充的列数,用于存储窗口滑动时的历史列数据(滑动窗口每次移动一列时,需保留前 WIN_SZ-1 列的像素以组成完整窗口)。整体第二维大小确保缓冲区能容纳 “并行输入的像素” 和 “窗口所需的历史列数据”,满足滑动窗口连续处理的需求。
XF_SNAME(WORDWIDTH) 是 Xilinx XF 库的宏,根据数据总线宽度 WORDWIDTH(如 8 位、16 位、32 位)自动匹配对应的硬件友好型数据流类型(例如 WORDWIDTH=8 时为 ap_uint<8>,WORDWIDTH=16 时为 ap_uint<16>)
unsigned char buf[WIN_SZ][(COLS >> XF_BITSHIFT(NPC))];
#pragma HLS ARRAY_PARTITION variable=buf complete dim=1
#pragma HLS RESOURCE variable=buf core=RAM_S2P_BRAM
第一维 WIN_SZ:对应滑动窗口的行数(如 7x7 窗口的WIN_SZ=7),即buf有WIN_SZ行,每行存储图像中连续多行的像素数据(供窗口提取行数据使用)。
第二维 (COLS >> XF_BITSHIFT(NPC)):由图像总列数和并行度共同决定:
COLS 是图像的总列数(宽度方向的像素总数);
XF_BITSHIFT(NPC) 是 Xilinx XF 库的宏,NPC(像素并行度,如XF_NPPC8表示 8 像素并行)决定了每周期处理的像素数,该宏返回log2(NPC)(如 NPC=8 时,XF_BITSHIFT(NPC)=3,因为 2³=8);
右移操作 COLS >> XF_BITSHIFT(NPC) 等价于 COLS / NPC,结果是并行处理时 “每周期处理的列数对应的总周期数”,即buf第二维的大小等于 “存储完整图像列数据所需的并行周期数”,确保能缓存整幅图像按并行度拆分后的列数据。
for(int init_row_ind=0; init_row_ind<win_size; init_row_ind++)
{
#pragma HLS LOOP_TRIPCOUNT min=WIN_SZ max=WIN_SZ
row_ind[init_row_ind] = init_row_ind;
}
初始化一个名为row_ind的数组,这个数组用于记录滑动窗口的行索引(Index)
read_lines:
for(int init_buf=row_ind[win_size>>1]; init_buf <row_ind[win_size-1] ;init_buf++)
{
#pragma HLS LOOP_TRIPCOUNT min=WIN_SZ max=WIN_SZ
for(col = 0; col < img_width>>XF_BITSHIFT(NPC) ; col++)
{
#pragma HLS LOOP_TRIPCOUNT min=TC max=TC
#pragma HLS pipeline
#pragma HLS LOOP_FLATTEN OFF
buf[init_buf][col] = srcmat.read();
}
}
read_lines:
for(int init_buf=row_ind[win_size>>1]; init_buf <row_ind[win_size-1] ;init_buf++)
{
#pragma HLS LOOP_TRIPCOUNT min=WIN_SZ max=WIN_SZ
for(col = 0; col < img_width>>XF_BITSHIFT(NPC) ; col++)
{
#pragma HLS LOOP_TRIPCOUNT min=TC max=TC
#pragma HLS pipeline
#pragma HLS LOOP_FLATTEN OFF
buf[init_buf][col] = srcmat.read();
}
}
读取图像数据,打到缓冲里面。
//takes care of top borders
for(col = 0; col < img_width>>XF_BITSHIFT(NPC); col++)
{
#pragma HLS LOOP_TRIPCOUNT min=TC max=TC
for(int init_buf=0; init_buf < WIN_SZ>>1;init_buf++)
{
#pragma HLS LOOP_TRIPCOUNT min=WIN_SZ max=WIN_SZ
#pragma HLS UNROLL
buf[init_buf][col] = 0;//buf[row_ind[win_size>>1]][col];
}
当窗口滑动到图像边缘(如顶部、底部、左侧、右侧)时,窗口的部分区域会超出原始图像的范围(即没有对应的像素数据)。为了保证窗口处理的完整性,通常需要对超出边界的区域进行填充(border padding)。通过给边缘补充0实现。
Row_Loop:
for(row = (win_size>>1); row < img_height+(win_size>>1); row++)
{
#pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS
P0 = 0;
ProcessFast<ROWS, COLS, DEPTH, NPC, WORDWIDTH, TC, WIN_SZ, WIN_SZ_SQ>(_src_mat, outmat, buf, src_buf,OutputValues, P0, img_width, img_height, shift_x, row_ind, row,win_size,_threshold,pack_corners);
//update indices
ap_uint<13> zero_ind = row_ind[0];
for(int init_row_ind=0; init_row_ind<WIN_SZ-1; init_row_ind++)
{
#pragma HLS LOOP_TRIPCOUNT min=WIN_SZ max=WIN_SZ
#pragma HLS UNROLL
row_ind[init_row_ind] = row_ind[init_row_ind + 1];
}
row_ind[win_size-1] = zero_ind;
} // Row_Loop
}Row_Loop:
for(row = (win_size>>1); row < img_height+(win_size>>1); row++)
{
#pragma HLS LOOP_TRIPCOUNT min=ROWS max=ROWS
P0 = 0;
ProcessFast<ROWS, COLS, DEPTH, NPC, WORDWIDTH, TC, WIN_SZ, WIN_SZ_SQ>(_src_mat, outmat, buf, src_buf,OutputValues, P0, img_width, img_height, shift_x, row_ind, row,win_size,_threshold,pack_corners);
//update indices
ap_uint<13> zero_ind = row_ind[0];
for(int init_row_ind=0; init_row_ind<WIN_SZ-1; init_row_ind++)
{
#pragma HLS LOOP_TRIPCOUNT min=WIN_SZ max=WIN_SZ
#pragma HLS UNROLL
row_ind[init_row_ind] = row_ind[init_row_ind + 1];
}
row_ind[win_size-1] = zero_ind;
} // Row_Loop
}
调用ProcessFast函数进行处理。逻辑如下:
若窗口大小win_size=5,初始row_ind = [0,1,2,3,4]:
第一步:保存row_ind[0] = 0到zero_ind;
第二步:数组向前移动一位,row_ind变为[1,2,3,4,4](最后一位暂时未更新);
第三步:将zero_ind(0)赋给最后一位,row_ind最终变为[1,2,3,4,0]。
此时,窗口的行索引整体向下滑动了一行,最顶部的行(0)被 “循环” 到最底部,适配下一行(row+1)的处理。
接下来的代码模块将只阐述代码作用, 原理以及实现方法。
xFnmsProc 函数
这个函数的核心是实现3x3 邻域的非极大值抑制(Non-Maximum Suppression, NMS),是图像处理中特征筛选的关键步骤。其原理和实现方法可从功能目标、核心逻辑及硬件适配设计三个层面展开说明:
一、核心原理:非极大值抑制(NMS)的作用与逻辑
非极大值抑制是特征提取后的经典后处理手段,目的是从密集的特征响应中筛选出局部最强的特征点,去除冗余的弱响应点,使最终输出的特征更稀疏、更具代表性。
在该函数中,具体逻辑基于 “3x3 局部邻域”:
对于每个待处理的 “中心像素”,将其特征响应值(如角点分数、边缘强度等)与周围 8 个相邻像素的响应值进行比较;
若中心像素的响应值大于所有 8 个邻域像素的响应值,则判定为 “局部极大值”,予以保留;
若中心像素响应值为 0(无有效特征),或小于任一邻域像素的响应值,则判定为 “非极大值”,予以抑制。
二、实现方法:从数据处理到硬件适配
该函数专为硬件加速(HLS)设计,实现上兼顾了功能正确性和硬件执行效率,核心方法包括:
1. 数据提取:固定邻域访问
函数从输入缓冲区src_buf中直接提取 3x3 邻域的 9 个像素响应值。缓冲区src_buf存储了局部区域的特征响应数据(16 位宽,实际有效信息为高 8 位,通过range(15,8)提取),其中:
中心像素对应src_buf[15][15](索引 15 为 3x3 邻域的中心);
8 个邻域像素分别对应中心像素的上、下、左、右及 4 个对角线位置(如src_buf[14][14]为左上角,src_buf[15][16]为右侧等)。
这种固定索引的访问方式在硬件中可通过并行线路直接读取,避免了复杂的地址计算,降低延迟。
2. 比较逻辑:并行化的局部极大值判断
核心比较逻辑通过一系列条件判断实现:若中心像素响应值(val4)同时大于 8 个邻域像素的响应值(val0~val8),则判定为局部极大值。
在硬件实现中,这 8 个比较操作可通过组合逻辑并行执行(而非软件中的顺序比较),大幅提升判断速度,适配硬件流水线的高吞吐量需求。
3. 结果输出:二值化标记
函数通过固定值对结果进行标记:
局部极大值(保留):输出 255;
非极大值(抑制):输出 127(包括中心像素响应值为 0 的情况)。
这种简单的二值化标记便于后续模块快速识别有效特征,减少数据传输量。
4. 硬件优化:适配 HLS 的设计
模板参数化:通过NPC(每周期处理像素数)、WIN_SZ(窗口大小)等模板参数,使函数可适配不同图像分辨率、特征窗口尺寸及硬件并行度(如一次处理 1 个或多个像素),提升代码复用性;
内联优化:#pragma HLS INLINE指令让函数被直接嵌入调用它的父函数,消除函数调用的硬件开销(如跳转、栈操作),优化电路时序和资源利用率。
Processfastnms 函数
这段代码主要功能是 在滑动窗口的列方向上处理图像数据,为非极大值抑制(NMS)准备邻域数据,并将处理结果打包输出,是快速特征提取(如FAST角点检测)流程中连接数据缓冲与特征筛选的关键环节。
一、核心功能与原理
函数的核心目标是 为每个列位置构建局部邻域数据,调用NMS函数筛选局部极大值,并将结果与原始邻域数据打包输出,支撑后续特征点的最终判定。 具体来说,在图像的每行处理中(结合外层Row_Loop),函数通过列方向的滑动窗口(Col_Loop),逐列完成以下工作:
1. 从输入流中读取图像数据,更新缓冲区,确保当前窗口包含足够的局部像素;
2. 为每个列位置提取对应的局部邻域数据(存储在src_buf中),作为NMS的输入;
3. 调xFnmsProc函数执行3x3邻域的非极大值抑制,得到当前位置的特征有效性标志; 4. 将邻域原始数据、NMS结果等打包成固定格式,通过输出流传递给后续模块。
二、数据处理流程 函数通过“缓冲更新→邻域提取→NMS处理→结果打包→窗口滑动”的闭环流程,实现列方向的连续处理,关键步骤如下:
1. 缓冲区初始化与准备
初始化src_buf(邻域数据缓冲区)为 0,避免初始值干扰;
定义buf_cop作为中间缓冲,用于临时存储当前窗口的行数据,并通过#pragma HLS ARRAY_PARTITION完全分区,实现硬件并行访问。
2. 列方向滑动窗口处理(Col_Loop)
这是核心循环,逐列遍历图像(含边界扩展),每列执行:
数据读取与缓冲更新:当行和列在有效图像范围内时,从输入流_src_mat读取数据到buf(全局缓冲区),确保buf始终存储最新的窗口行数据;
邻域数据提取:根据当前行索引row_ind和列col,从buf中复制对应行的数据到buf_cop,再更新到src_buf(局部邻域缓冲区)。针对图像底部边界(row > img_height-1),通过索引调整复用已有数据,保证边界处邻域的完整性;
NMS 处理:调用xFnmsProc函数,基于src_buf中的 3x3 邻域数据执行非极大值抑制,结果存入OutputValues;
有效性判断与结果打包:当列超过窗口半宽(col >= WIN_SZ>>1)时,将 NMS 结果(validFlag)标记为有效,否则标记为 0(边界区域无效);将邻域原始数据(winVal)、有效性标志(validFlag)、中心像素值等打包成 264 位的temp,写入输出流datapackStreamOut;
窗口滑动更新:通过循环移位更新src_buf,将列方向的邻域数据左移一位,为下一列处理准备新的邻域(类似行方向的循环缓冲机制,避免重复读取数据)。
3. 边界与特殊情况处理
针对不同的NPC(每周期处理像素数),调整列循环变量col_loop_var,适配不同并行度的硬件处理;
对图像底部边界(row超出图像高度),通过索引映射复用buf中已有数据,避免访问无效内存;
对列方向的初始边界(col < WIN_SZ>>1),直接标记validFlag为 0,避免边界处无效特征的干扰。
三、硬件优化设计
函数针对 HLS 硬件实现做了深度优化,确保高吞吐量和低延迟:
内联优化:#pragma HLS INLINE将函数嵌入调用者,消除函数调用开销;
数组分区:buf_cop完全分区(ARRAY_PARTITION complete),实现并行读写,提升数据访问速度;
循环优化:内层循环通过#pragma HLS UNROLL展开,消除迭代延迟;外层Col_Loop使用#pragma HLS pipeline实现流水线,理想情况下每个时钟周期处理一列数据;
参数化设计:通过模板参数(ROWS、COLS、NPC等)适配不同图像尺寸、并行度和窗口大小,提高代码复用性,同时让 HLS 工具能根据参数优化硬件资源分配。
xFfastnms 函数
这个函数是基于 HLS 的快速特征提取 + 非极大值抑制(NMS)的完整硬件加速流水线顶层函数,整合了之前所有子函数的逻辑,实现从原始图像输入到带 NMS 结果的结构化数据输出的端到端处理,核心用于实时图像处理场景(如 FAST 角点检测)的硬件实现。其原理、实现架构及硬件优化设计如下:
一、核心原理:二维滑动窗口 + NMS 的端到端流水线
函数的核心逻辑是通过 “行 - 列二维滑动窗口” 遍历全图,结合边界处理和非极大值抑制,从原始图像中筛选出局部极大特征点,并将结果打包输出。
整体流程遵循 “准备 - 处理 - 滑动” 的闭环:
先初始化滑动窗口的行索引、缓冲区,读取初始图像数据并处理顶部边界,确保窗口在边缘区域仍有有效数据;
以行为单位遍历全图(含边界扩展),每行中通过列方向滑动窗口提取局部邻域数据;
对每个邻域执行 NMS 筛选,保留局部极大特征点;
窗口逐行、逐列滑动,通过循环缓冲机制复用数据,避免重复读取,提升效率;
最终将邻域原始数据、NMS 结果等打包成固定格式输出,供后续模块(如特征点坐标计算)使用。
二、实现架构:分层模块整合与数据流转
函数通过模块化设计整合了数据初始化、缓冲管理、边界处理、核心计算和结果输出,各环节紧密衔接形成流水线:
1. 参数与缓冲区配置(硬件适配基础)
定义核心缓冲区:row_ind(行索引数组)、buf(全局图像数据缓冲区)、src_buf(局部邻域缓冲区)、OutputValues(NMS 结果缓冲区)。
硬件优化配置:
对所有缓冲区使用#pragma HLS ARRAY_PARTITION complete(维度 1 或双维度),实现缓冲区的完全并行访问(硬件中多个端口同时读写),消除数据访问瓶颈;
明确buf的硬件资源类型为RAM_S2P_BRAM(单端口读、双端口写的块 RAM),平衡硬件资源占用(BRAM 比寄存器更节省资源,适合存储大量图像数据)。
2. 初始化阶段:索引与数据准备
行索引初始化:生成长度为win_size的row_ind数组,元素值等于自身索引(如row_ind[0]=0、row_ind[1]=1),为滑动窗口的行位置定位提供基础。
初始数据读取:通过read_lines循环,从输入流_src_mat读取 “窗口中间行到末尾行” 的图像数据到buf,为首次窗口处理铺垫初始数据。
顶部边界处理:将缓冲区顶部WIN_SZ>>1行(超出图像顶部的边界区域)的数据,复用窗口中间行的数据(而非填 0),确保边界处邻域数据的一致性,避免特征误判。
3. 核心处理:行遍历 + 列方向流水线(调用子函数)
外层行遍历(Row_Loop):这是顶层主循环,遍历范围覆盖 “窗口半宽→图像高度 + 窗口半宽”(含顶部和底部边界扩展),确保全图(含边缘)都被处理。
每行核心逻辑:调用Processfastnms子函数,完成当前行的列方向滑动窗口处理 —— 包括读取更新图像数据、提取 3x3 邻域数据、调用xFnmsProc执行 NMS、打包输出结果。
行索引滑动更新:每行处理完毕后,通过 “循环缓冲机制” 更新row_ind(将最顶部索引移到最底部,其余索引上移 1 位),模拟窗口向下滑动 1 行,无需重新初始化索引,硬件实现高效。
4. 结果输出:结构化数据打包
通过datapackStreamOut输出流,将 “局部邻域原始数据 + NMS 有效性标志 + 中心像素特征值” 打包成 264 位的固定格式数据,为后续模块(如特征点坐标筛选、输出显示)提供结构化输入,减少数据传输开销。
三、硬件优化设计:面向高吞吐量的 HLS 优化
函数的所有设计都围绕 “硬件并行性、低延迟、资源高效” 展开,核心优化点:
完全并行的缓冲区访问:所有缓冲区的完全分区(ARRAY_PARTITION complete),让硬件可同时读写缓冲区的多个元素,匹配流水线的并行处理节奏。
资源精准分配:buf指定为 BRAM 资源,避免使用大量寄存器导致资源溢出,同时 BRAM 的高带宽适配图像数据的高速读写。
循环优化组合:内层循环使用#pragma HLS pipeline(流水线)、#pragma HLS UNROLL(展开),外层循环用#pragma HLS LOOP_TRIPCOUNT(迭代次数提示),让 HLS 工具生成高时序性能的电路 —— 理想情况下可达到 “每时钟周期处理 1 个列数据” 的吞吐量。
参数化与复用:通过模板参数(ROWS、COLS、NPC等)适配不同图像分辨率、窗口大小、每周期处理像素数(NPC),无需修改核心逻辑即可适配不同硬件平台和应用场景。
myFAST函数
这两段代码是FAST 角点检测的硬件加速入口级代码,基于 Xilinx HLS 实现,核心作用是搭建 “输入解析→多分辨率适配→核心检测调度→标准化输出” 的顶层框架,衔接外部数据流与底层 FAST 角点检测核心逻辑(含之前提到的 NMS),是 FPGA 等硬件上实现实时 FAST 角点检测的 “总入口”。其原理、实现架构及硬件适配设计如下:
一、核心原理:FAST 角点检测的硬件加速入口封装
FAST(Features from Accelerated Segment Test)角点检测是一种高效的特征提取算法,核心是通过比较像素邻域的灰度值快速判断是否为角点。这两段代码并未直接实现 FAST 的核心判断逻辑,而是为底层核心检测函数(xFFastCornerDetection)提供顶层支撑:
标准化外部输入输出接口,适配 AXI-Stream(FPGA 常用高速数据流接口);
支持多分辨率图像适配,根据输入的 “图像层级” 自动选择对应分辨率;
封装模板参数,固化检测配置(如是否启用 NMS、像素格式、并行度);
通过 HLS 指令优化硬件流水线,确保数据高速流转,匹配实时处理需求。
二、实现架构:两层函数分工与数据流转
代码分为 “顶层加速器入口(fast_accel)” 和 “检测函数封装(myFAST)” 两层,分工明确、数据流转简洁:
1. 顶层入口函数 fast_accel:外部接口与输入解析
作为整个 FAST 加速器的 “对外接口”,负责对接外部数据流、解析配置信息、调度核心检测逻辑,是硬件与外部交互的关键:
接口标准化配置:
#pragma HLS INTERFACE ap_ctrl_none port=return:禁用 HLS 默认生成的控制接口(如 start、done 信号),适配纯数据流驱动的硬件场景(无需外部控制信号,数据来了就处理);
#pragma HLS INTERFACE axis register both port=srcStream/MomentsStreamOut:将输入 / 输出接口配置为 AXI-Stream 标准接口(FPGA 高速数据传输的常用接口),且 “双向寄存器化”(接口信号经过寄存器缓冲),提升硬件时序性能(减少信号延迟,避免时序违规)。
核心功能:
解析输入图像层级:从输入流srcStream先读取 1 个 8 位数据img_level(图像层级标识,0-3);
多分辨率适配:预定义 4 组分辨率数组(_image_height/_image_width),根据img_level自动选择对应图像尺寸(如img_level=0时,分辨率为 640x480;img_level=3时为 190x142),支持多尺度图像处理;
传递配置与调度:将图像层级信息打包后写入输出流,再调用myFAST函数,传入适配后的分辨率参数,启动核心检测。
2. 封装函数 myFAST:模板参数固化与核心调用
作为中间封装层,核心作用是 “固化检测配置 + 调用底层核心函数”,简化顶层调度逻辑:
模板参数固化:通过模板参数明确检测配置,无需在运行时动态配置,适配硬件 “编译时确定” 的特性:
NMS=1:启用非极大值抑制(对应之前分析的xFnmsProc逻辑),筛选冗余角点;
SRC_T=XF_8UC1:输入图像为 8 位单通道灰度图(FAST 角点检测默认输入格式);
ROWS/COLS:图像最大分辨率(编译时确定,适配硬件资源分配);
NPC=1:每时钟周期处理 1 个像素(可根据硬件资源调整为 2/4/8,提升并行度)。
硬件优化指令:
#pragma HLS inline off:禁止函数内联,将myFAST保留为独立模块,便于 HLS 工具单独优化时序,也方便后续代码调试与复用;
#pragma HLS DATAFLOW:启用数据流优化,让函数内部的 “数据读取→核心处理→结果输出” 形成流水线并行(前一个数据的处理未结束,下一个数据已开始读取),大幅提升吞吐量。
核心调用:直接调用底层 FAST 角点检测函数xFFastCornerDetection,将顶层传入的输入流、输出流、分辨率参数传递下去,触发核心检测逻辑(包括角点快速判断、NMS 筛选等)。
三、数据流转全流程(从输入到输出)
外部输入:8 位灰度图像数据流通过srcStream(AXI-Stream 接口)传入;
层级解析:fast_accel先读取 1 个 8 位img_level,确定当前图像分辨率;
配置传递:将img_level打包为 88 位数据写入MomentsStreamOut,同时将适配后的分辨率(_image_height[img_level]/_image_width[img_level])传入myFAST;
核心检测:myFAST调用xFFastCornerDetection,底层完成 FAST 角点快速检测 + NMS 筛选;
结果输出:检测结果(含角点信息、邻域数据等)通过MomentsStreamOut(88 位 AXI-Stream)输出,供后续模块(如角点坐标提取、图像匹配)使用。
四、核心价值:硬件加速的顶层适配
这两段代码的核心作用是 “适配硬件、简化调度、标准化接口”,而非直接实现算法逻辑:
对外部:提供 AXI-Stream 标准接口,可直接对接 FPGA 的高速 I/O 模块(如 HDMI 接收、DDR 读写);
对内部:固化配置、支持多分辨率,让底层核心函数无需关注接口与适配,专注算法本身的硬件优化;
性能保障:通过DATAFLOW、接口寄存器化等 HLS 指令,确保数据流转无瓶颈,匹配底层检测逻辑的并行处理节奏,最终实现 “实时” 角点检测(如 640x480 分辨率下每秒处理 30 帧以上)。
ORB-SLAM3硬件加速项目系列

点击文章下方标签获取整个系列更新文章!
文章doc版链接【金山文档 | WPS云文档】 FAST角点检测 HLS代码解析
本章是“FAST角点检测 HLS代码解析”最后一章节,至此已将FAST角点检测的各个模块详细解析清楚,后续有时间会更新总结性文章。