免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

基于FPGA的SAD模板匹配目标跟踪:从算法到Verilog实现

基于FPGA的SAD模板匹配目标跟踪:从算法到Verilog实现 如果你在嵌入式视觉这条路上摸爬滚打过一阵子大概率会碰上这样的需求要在视频流里锁定一个目标实时输出它的坐标还要把资源压到一块不至于太贵的FPGA上。ARM端跑OpenCV虽然省事但一到720p、30fps就捉襟见肘NPU方案又把人绑在特定框架里调试起来头大。于是很多人开始把目光转向FPGA用硬件流水线去扛像素级运算。而SADSum of Absolute Differences绝对差值和模板匹配可以说是最适合在FPGA上落地的跟踪算法之一。它没有乘法、没有除法、没有浮点全是加法和绝对值流水线一拍一拍往下推数据到了就能算天然契合FPGA的并行特性。这篇文章就围绕“基于FPGA的SAD模板匹配目标跟踪”这个项目从算法选型、硬件架构、Verilog实现到上板调试把一条完整的技术路线摊开讲清楚。适合正在做FPGA图像处理、准备搞目标跟踪项目、或者想从软件算法迁移到硬件加速的工程师参考。1. 方案整体设计与思路拆解1.1 为什么是FPGA而不是ARM或者GPU目标跟踪这个需求落到嵌入式平台上通常有三个选择ARM端的软件实现、GPU/NPU端的并行加速、FPGA端的硬件流水线。三者各有适用场景但做实时视频跟踪时FPGA在两方面优势很明显。第一个优势是确定性时延。ARM上跑算法受操作系统调度、Cache命中率、内存带宽波动影响每一帧的处理时间并不固定。而FPGA里一旦把流水线搭好输入一个像素到输出匹配结果的时钟周期数是固定的这在需要和外部设备联动的场景里特别重要。比如云台随动、机械臂抓取、无人机视觉定位控制周期一旦抖动整个系统就跟着抖。第二个优势是功耗与算力的平衡。一块中端FPGA跑720p的SAD模板匹配整板功耗几瓦到十几瓦比GPU低一个数量级。加上FPGA不需要跑系统、不用搬移大块数据像素从CMOS传感器进来经过灰度转换、SAD计算、坐标输出全程都在芯片内部流转省掉了大量DDR带宽。当然FPGA也不是万能的开发周期长、迭代慢是它的老毛病。但SAD算法结构规整、数学形式简单正好把FPGA的优势发挥出来避开它的短板。这也是我在这个项目里选FPGA作为计算平台的核心原因。1.2 为什么选SAD而不是SSD或者NCC模板匹配的相似度度量方法有好几种最常用的三个是SAD、SSD差值的平方和和NCC归一化互相关。三者的数学表达式如下SADSAD(u,v) ΣΣ|I(xu, yv) − T(x,y)|SSDSSD(u,v) ΣΣ[I(xu, yv) − T(x,y)]²NCCNCC(u,v) (ΣΣI(xu, yv)·T(x,y)) / (σI·σT)从数学复杂度来看NCC对光照变化最鲁棒因为它等于做了归一化把整体亮度和对比度的影响都去掉了。SSD中间项是平方可以展开成相关运算这在某些硬件架构里能用快速算法。而SAD就是纯绝对值累加。但硬件实现这件事讲究的是“够用就好”。NCC在FPGA里要算均值、方差、乘法、除法还要做浮点近似资源消耗翻好几倍实时性很难保证。SSD里的平方运算虽然可以用DSP切片做但DSP资源本来就要留给其他模块或者直接把平方操作换成查表可查表又打乱了流水线的简洁性。SAD就不一样了绝对值差 比较后取反加一累加 简单的加法树。整个计算单元只需要加法器和减法器消耗的全是FPGA里最富余的逻辑资源LUT和FF。实测下来一个32×32模板的SAD计算阵列在Xilinx Artix-7系列上只用不到5000个LUT却能跑出超过200MHz的时钟频率而同样规模的NCC实现LUT占用至少翻两倍性能还未必追得上。还要考虑一个实际问题目标跟踪的场景里帧与帧之间的光照变化通常不大而且我们可以通过灰度归一化、直方图均衡等预处理把光照影响压到最低。既然预处理能解决的问题就没必要让算法承担额外的计算负担。所以做FPGA目标跟踪SAD是性价比最高的选择。1.3 系统级架构从摄像头到坐标输出整个系统不是孤立地跑一个SAD模块而是一条完整的数据通路。以我做的这个项目为例输入是OV5640摄像头输出的RGB数据经过灰度转换后进入SAD跟踪模块再把结果通过UART或者HDMI叠加输出。顶层数据流是摄像头采集 → Bayer转RGB → RGB转灰度 → 帧同步与行缓存 → SAD匹配计算 → 目标坐标 → 坐标滤波 → 输出叠加前面三步是预处理中间两步是核心计算后面两步是后处理。值得强调的是帧同步与行缓存这一步非常关键。SAD模板匹配需要同时拿到模板数据和搜索区域数据而搜索区域数据往往横跨多行像素所以必须用行缓存Line Buffer把若干行数据存下来等滑动窗口的数据凑齐了才能开始算。后处理的坐标滤波我在项目里用了卡尔曼滤波。SAD匹配虽然能在稳定场景下输出准确坐标但目标被遮挡、快速遮挡恢复的时候匹配结果往往会跳变。卡尔曼滤波根据目标运动模型对坐标做预测和校正能有效抑制这种跳变。关于这块我在后面“算法优化”章节会展开讲。2. 核心算法细节拆解2.1 SAD公式与匹配流程SAD匹配的思路用大白话讲就是“模板对齐”。想象你要在一幅密密麻麻的墙砖照片里找到一块特别标记的砖最笨的办法就是拿着那块砖的图片从左上角开始一格一格贴上去比对看哪一处的差异最小。在数学上这个“比对”就是公式SAD(u,v) ΣΣ|I(xu, yv) − T(x,y)|。其中T是模板尺寸为M×NI是待搜索的图像帧(u,v)是模板左上角在图像中的位置。计算时模板在搜索区域内滑动每到一个位置就计算一次SAD值最终取SAD值最小的位置作为匹配结果。整个流程分四步模板初始化在第一帧或者系统空闲时由上位机给定目标中心的坐标以该坐标为中心截取一块区域作为模板。搜索区域提取下一帧到来时以上一帧目标中心为中心向四周扩展一定范围这个范围就是搜索区域。SAD计算在搜索区域内逐点移动模板计算每个位置的SAD值并记录最小值及其位置。结果更新用匹配到的位置更新目标中心坐标进入下一帧继续跟踪。这里有个细节需要特别注意模板是在第一帧截取的但目标在运动过程中会发生变化比如旋转、尺度变化、形状变化。SAD对旋转和尺度变化非常敏感目标一旦变大缩小匹配就会失败。因此工业级的SAD跟踪通常会和目标尺寸估计模块配合使用定期更新模板。2.2 搜索策略与窗口设计如果对整帧图像做全搜索计算量会非常惊人。以一帧720p1280×720图像为例32×32模板全搜索意味着大约120万个候选位置每个位置要算1024次像素差值累加共约12亿次操作。这对FPGA来说依然是可以做的但代价是占用大量逻辑资源和功耗完全没有必要。更合理的方案是设置一个搜索区域以上一帧目标位置为中心比如扩展64×64像素的区域。这样候选位置数量骤降同时匹配速度大幅提升。我实测在64×64搜索区域内32×32模板能做到几十微秒内完成全部计算对720p30fps的视频流来说性能冗余绰绰有余。搜索区域内做全搜索即可不必上三步搜索或者菱形搜索这类快速策略。原因很简单搜索区域已经很小全搜索硬件结构最规整、时序最简单能稳定跑在最高频率综合下来全搜索反而是最优解。窗口尺寸则需要根据目标大小灵活配置。模板太小比如8×8特征太少容易产生误匹配模板太大比如64×64对目标变化过于敏感而且计算单元代价高。我的经验是模板尺寸取目标在图像中实际像素大小的70%到90%比较合适既保留了足够的纹理特征又留出一定的变化冗余。2.3 帧差法辅助粗定位SAD匹配有个天生的短板模板一旦建立它找的不是“运动的目标”而是“和模板最像的区域”。如果画面里出现一个和模板纹理类似但静止的背景物体SAD会把目标定位到那个背景物体上。为了解决这个问题我引入了帧差法做粗定位。帧差法利用目标运动导致相邻帧差异这一特性先计算出运动区域的外接矩形框再把这个矩形框作为SAD搜索区域的约束条件。这样SAD匹配只在运动区域内进行背景中相似纹理的干扰就被过滤掉了。两帧差分法的公式是D(x,y) |I_t(x,y) − I_{t−1}(x,y)|超过阈值则判定为运动像素。帧差法本身实现起来极其简单在FPGA里只需要一组FIFO缓存上一帧数据再配合减法器和比较器就能完成资源占用可以忽略不计。但它的效果立竿见影没有运动区域约束时SAD误匹配率可能超过30%有了约束之后误匹配率能压到5%以下。这套“帧差粗定位 SAD精匹配”的组合是我在实际项目里用得最顺手的一套方案。它不像光流法那样需要复杂的迭代计算也不像深度学习目标检测那样需要大算力但它稳定、可控、易于调试特别适合嵌入式实时场景。3. 硬件架构设计与模块实现3.1 顶层模块划分FPGA工程的模块划分直接影响后端的时序收敛和调试效率。这个项目的顶层模块我拆成了五个子模块图像采集与预处理模块cap_preprocess负责接收摄像头数据、完成灰度转换、输出同步信号。帧缓存模块frame_buf用BRAM缓存上一帧灰度图像供帧差法使用。SAD计算引擎sad_engine核心计算模块包含搜索区域行缓存、模板存储、SAD计算阵列和最小值追踪逻辑。坐标后处理模块track_post实现卡尔曼滤波、坐标平滑和超限判定。输出与上位机接口模块io_top负责把目标坐标打包成UART帧或者在HDMI输出上叠加十字光标。模块之间用AXI-Stream接口连接数据以像素流的形式在模块间流动。接口统一了每个模块之间只需要约定好ready/valid握手协议联调时就能少很多麻烦。3.2 SAD计算阵列的并行设计SAD计算的本质是一个二维滑动窗口遍历硬件加速的关键在于并行度选择。我这次的模板尺寸是32×32搜索区域64×64这样总的候选位置数是33×331089个。如果顺序计算每个位置1024次累加总计算量为1089×1024≈111万次加法操作。全并行计算每个候选位置需要1024个减法器和1024个加法器资源爆炸。而完全顺序算时钟周期数又太多。折中方案是行并行加流水线每次同时计算模板一整行的32个像素差绝对值这32个结果通过加法树逐步累加再用一个状态机逐行累加32行最后得到该候选位置的SAD值。这样算下来计算一个候选位置需要大约32个时钟周期的延迟1089个候选位置共耗时约35000个周期。跑在150MHz下耗时约233微秒。一帧720p图像有约40毫秒的帧间隔计算性能绰绰有余。实际工程里还有一个性能优化技巧叫滑动窗口数据复用。模板在搜索区域滑动时相邻两个候选位置之间有大量重叠像素SAD计算时这两个位置的输入数据有大量重复。我通过合理的行缓存和数据调度让每个新进入的像素为多个候选位置共享使用最终把等效计算效率提升了近一倍。3.3 行缓存与数据复用的资源计算SAD计算引擎里最占资源的就是搜索区域的行缓存。搜索区域宽度是64像素缓存的行数是模板高度32行总缓存大小是64×32×8bit16Kbit用一块BRAM就能装下。这里有个关键的硬件设计点滑动窗口在行方向移动时每来一个新像素窗口整体的数据需要全部更新吗当然不是。窗口向右滑动一格时只有最右边新增的一列数据是新的其余31列数据都是从上一拍缓存下来的。利用这个特性我用移位寄存器SRL结构实现了一组“列滑动寄存器”每个新像素只需要推入32个寄存器链条其他数据自然滚进对应位置。这样设计的好处是处理一个候选位置的延迟缩短到仅仅1个时钟周期把32行数据全部推到位后流水线连续输出32个部分和整个搜索区域的SAD计算可以在约2100个周期内完成比逐位置独立计算快了16倍以上。3.4 搜索状态机与流程控制SAD计算引擎的内部状态机是整个模块的“指挥中心”。状态机分为IDLE、TEMPLATE_LOAD、SEARCH_PREPARE、SEARCH_RUN、RESULT_OUT五个状态。IDLE等待外部触发信号收到新帧同步信号后跳转到TEMPLATE_LOAD。TEMPLATE_LOAD从BRAM读取模板数据填充到模板寄存器阵列中。同时拉取搜索区域的起始地址。SEARCH_PREPARE行缓存开始填充等待搜索区域的前32行数据和首列数据全部到位。SEARCH_RUN启动SAD计算阵列状态机不断产生地址和控制信号驱动窗口在搜索区域内滑动。每完成一个位置的计算就把结果与当前最小值比较。RESULT_OUT把所有候选位置都算完后输出最小值对应的坐标回到IDLE等待下一帧。时序上最需要小心的是SEARCH_RUN阶段。窗口滑动过程中新数据到达和计算的完成必须严格对齐一旦错拍计算阵列就会拿到错误的数据产生错误的SAD结果。我在调试时设置了一个计数器确保每两拍产生一个新的候选位置坐标同时SAD计算阵列的输出延迟固定为N拍这样在数据上做对齐就很容易了。3.5 时序约束与资源评估FPGA工程里不写时序约束等于裸奔。尤其像SAD计算阵列这种高频、大规模并行逻辑综合后的默认布局往往无法满足时序要求。我在Vivado里对时钟做了一个主约束频率定为150MHzArtix-7完全可以稳定跑同时对像素输入打了两级寄存器提高时序余量。资源消耗方面我做一次完整评估的结果如下Artix-7 XC7A35T为例LUT约11,200占总量的17%左右。FF约7,800占总量的12%左右。BRAM18块占总量的35%左右主要是行缓存和帧缓存。DSP切片0个。这验证了SAD算法几乎不需要DSP资源全部靠LUT/FF实现。最大时钟频率综合后报告是182MHz留给150MHz主时钟大约20%的余量。整体资源占用完全在单片中等FPGA的承受范围内还留出了大量空间给后续扩展比如加颜色特征、直方图统计或者其他跟踪算法。4. 实操过程从Vivado工程到上板验证4.1 工程搭建与最关键的设计参数项目实践阶段我选用的是Xilinx Artix-7系列FPGA开发环境是Vivado 2020.2。之所以选Artix-7而不是Kintex或者UltraScale是因为这个项目的资源需求不大、逻辑规模中等Artix-7的性价比已经足够而且它的生态资料最全遇到问题能找到大量参考。核心设计参数如下摄像头OV5640RGB565输出分辨率1280×720帧率30fps。灰度转换RGB转灰度采用整数近似公式Y (77R 150G 29B) 8避免浮点计算。模板尺寸32×32像素从第一帧目标框中心截取。搜索区域64×64像素以前一帧目标坐标为中心。帧差法阈值308bit灰度值。SAD计算并行度32行并行加法树深度5级。坐标输出UART 115200bps每帧发送一次目标坐标。这几个参数不是拍脑袋定的而是根据前面的计算和实测反复调整出来的。特别是模板尺寸我一开始用的是64×64结果资源占用翻倍、时序收敛困难随后缩到32×32在保持匹配准确率基本不变的前提下性能余量增加了一大截。4.2 SAD核心模块的Verilog实现要点这里把SAD计算阵列的核心代码思路拆给大家看。完整的Verilog代码量比较大但关键的实现思路就三点行缓存、行并行、树形累加。第一个关键实现是行缓存。搜索区域的每一行数据通过一个移位寄存器链输入每行有64个像素每个像素8bit。当新像素到达时它被同时推入所有行的移位寄存器从而实现多行数据同步滚动。第二个关键实现是行并行。SAD计算单元包含32个“行SAD模块”每个模块负责计算模板一行与搜索区域对应行的绝对差之和。输入的模板数据和搜索数据都按行组织成数组计算时逐行对齐。第三个关键实现是树形累加。32路行部分和通过一个5级加法树逐级相加得到最终的SAD值。加法树的每一级输出都打一拍寄存器形成流水线保证时序稳定。以下是核心代码的简化示意// 行SAD模块计算模板一行与搜索区域一行的绝对差之和 module sad_row #( parameter ROW_LEN 32 )( input wire [7:0] template_data [0:ROW_LEN-1], input wire [7:0] search_data [0:ROW_LEN-1], output reg [11:0] sad_partial ); integer i; always (*) begin sad_partial 12b0; for (i 0; i ROW_LEN; i i 1) begin sad_partial sad_partial (template_data[i] search_data[i] ? template_data[i] - search_data[i] : search_data[i] - template_data[i]); end end endmodule // SAD计算阵列顶层 module sad_array #( parameter TEMPLATE_SIZE 32, parameter SEARCH_SIZE 64 )( input wire clk, input wire rst_n, input wire [7:0] search_pixel, input wire search_valid, output reg [15:0] sad_min, output reg [7:0] match_x, output reg [7:0] match_y, output reg result_valid ); // 行缓存与模板存储略... // 核心逻辑 // 1. 使用一个32×32的模板寄存器阵列存储模板数据。 // 2. 使用32个行缓存存储搜索区域当前窗口数据。 // 3. 每个时钟周期当窗口滑动时更新一个候选位置的SAD值。 // 4. 与当前最小值比较更新匹配坐标。 // 5. 搜索完成后输出result_valid和匹配坐标。 endmodule这个代码思路看起来简单但真正确保它能正确工作的是状态机和数据调度的严密配合。建议各位在做仿真的时候先用一个手动算好的小尺寸例子做测试比如4×4模板、8×8搜索区域数据全部用手工计算比对通过后再扩展到32×32。4.3 仿真验证方法与关键测试向量仿真这一步千万别偷懒。我见过很多项目看波形觉得差不多就上板结果等到联调时问题一大堆最后回来补仿真反而浪费了更多时间。我的经验是仿真至少做三层。第一层是纯逻辑仿真用iverilog或者Vivado Simulator跑验证SAD计算单元的计算结果是否正确。测试向量用Python脚本随机生成模板和搜索区域同时用Python实现SAD算法比对硬件输出和软件输出。这个比对工具非常管用往往能发现加减符号反了、位移错误这类低级bug。第二层是带时序的布线后仿真验证SAD计算阵列的流水线能否在150MHz时钟下稳定运行。布线后仿真能暴露时序最坏路径的问题虽然跑起来很慢但一定要跑到最关键的模块。第三层是系统级验证在仿真环境里模拟摄像头时序信号把一整帧720p图像灌进去验证帧同步、行缓存的填充、SAD搜索流程、坐标输出全链路是否正常。这一步通过后上板几乎没有大的意外。4.4 板上调试与效果实测上板调试阶段我把工程比特流烧录后通过UART把目标坐标实时传回PC在PC端用Python脚本接收并绘图显示就能直观看到跟踪轨迹。实际效果是这样的在室内场景下一个人拿着目标物体缓慢移动系统能以30fps实时输出坐标平均误差在2到3个像素以内。快速挥手或者鼠标快速移动时偶尔会出现一帧的跳变但卡尔曼滤波能把这些跳变大部分吸收轨迹保持平滑。硬件性能方面实测整板功耗约6.5W包括PHY和所有外设SAD计算引擎的功耗估算在2W左右完全符合中端FPGA项目的量级。这台系统的问题是目标一旦被完全遮挡超过1秒再出现由于模板没有更新匹配容易丢失在目标快速移动使窗口剧烈运动时搜索区域的64×64范围可能覆盖不住目标。针对这两个问题我在后续版本中加入了模板学习和缩小搜索范围的自适应策略效果有显著改善。5. 常见问题与排查技巧实录5.1 高频问题速查表项目做完我把调试过程中最常遇见的几类问题整理成一个表方便后续做类似项目时快速定位。现象SAD输出的匹配坐标总在某一个固定位置不会变化。 可能原因模板加载模块没有正确执行模板数据全是0。 排查方法用ILA抓取模板寄存器阵列的输入确认第一帧目标区域的灰度值是否正确写入。现象匹配结果随机跳变相邻帧坐标差异巨大。 可能原因搜索区域行缓存没有对齐或者SAD计算阵列流水线打拍不对导致数据错位。 排查方法先用固定模板、固定搜索区域测试验证SAD值是否与软件计算结果一致。现象帧率达不到30fps画面明显卡顿。 可能原因SAD计算的花费时钟数超过了帧间隔预算或者后续卡尔曼滤波和UART发送引入了过长阻塞。 排查方法用Vivado的时序报告确认时钟频率用计数器统计每帧实际计算周期数。现象追踪目标在光照忽明忽暗时丢失。 可能原因SAD对整体光照变化敏感。 排查方法在预处理阶段增加亮度均值归一化或者定期用帧差法检测运动区域并更新模板。现象综合后时序不收敛时钟频率上不去。 可能原因SAD计算阵列里的加法树没有充分打拍导致组合逻辑路径过长。 排查方法在加法树每两级之间插入寄存器或者提高整个模块的流水线深度。上板调试还有一个通用技巧叫做“指示灯排查法”。在FPGA里拉出几个GPIO接LED分别表示“模板加载完成”“搜索进行中”“搜索结果有效”“卡尔曼锁住”等状态。一旦出问题看LED就知道卡在哪个环节比盯着ILA波形刷屏高效得多。5.2 卡尔曼滤波与坐标平滑的配合SAD匹配输出坐标的频率是每帧一次但目标运动是连续时间过程。我在后处理模块中用卡尔曼滤波做了时间和空间的双重平滑。卡尔曼滤波的模型是这样的状态量是目标的中心坐标和速度共4维观测量是SAD输出的坐标共2维。状态方程假设匀速运动观测方程假设坐标直接测量。噪声参数方面过程噪声方差我取1.5像素²观测噪声方差取4像素²。实际调参经验是过程噪声设得小一点滤波出来的轨迹更平滑但对突然加减速敏感过程噪声设得大一点响应更快但轨迹会有更多抖动。我最后选了1.5这个中间值既保证了平滑又能跟上普通速度的挥手动作。卡尔曼滤波还有一个额外的好处当模板匹配连续几帧失败时可以用滤波预测的坐标暂时顶住输出给模板恢复争取时间。这个特性在目标短暂被遮挡时的表现特别明显。5.3 我踩过的三个坑第一个坑是SAD计算阵列的流水线深度不够导致时序不收敛。当时为了省资源我把加法树的寄存器去掉了一级结果综合报告显示最差路径超过时钟周期40%布线直接不通过。后来老老实实按照5级流水线做性能立刻达标。第二个坑是模板更新策略过于激进。我最初尝试每帧都更新模板结果目标稍微有点遮挡模板就被污染了后面几帧的匹配质量急剧下降。后来改成“低置信度不更新”策略SAD最小值超过某个阈值时就不更新模板目标恢复稳定后才重新学习。第三个坑来自于帧差法阈值设置。阈值设太高时慢速运动的目标检测不到导致搜索区域缩得很小匹配结果漂移阈值设太低时噪声被当成运动像素搜索区域反而变得过大计算量和误匹配率都上来了。最后我用自适应阈值取当前帧差图均值加上2倍标准差效果稳定。6. 后续演进从基础SAD到系统级的几个扩展方向这个项目做完以后我一直在思考SAD模板匹配能往哪些方向走。纯SAD的确有很多局限但它最大的价值在于为整个FPGA图像处理系统搭好了一个稳定的框架后续扩展都是在这个框架上修修补补。第一个扩展方向是引入金字塔分层匹配。把图像和模板都做高斯金字塔下采样先在低分辨率层粗匹配再把结果映射到高分辨率层精匹配。这样做的好处是当目标快速移动时不需要扩大搜索区域而是通过不同分辨率的匹配获得粗到细的定位。金字塔层数一般取3层资源开销增加不到30%但搜索范围可以扩大一个量级。第二个扩展方向是融合多特征。灰度SAD对纹理不敏感但颜色信息对目标跟踪非常有用。可以在灰度SAD的基础上增加一段直方图匹配模块两者结果加权融合。FPGA里实现起来也不难只是多一块BRAM存直方图计算开销主要是直方图相交运算。第三个扩展方向是配合AI检测器做目标重定位。在监控场景里目标长时间被遮挡后重新出现SAD很难找回目标。如果系统中还有一个人工智能检测模块哪怕是极轻量级的YOLO tiny就可以在SAD连续丢失若干帧后切换到AI检测器的粗定位结果重新初始化模板。我自己用ZYNQ平台验证过这个方案FPGA部分跑SAD跟踪ARM部分跑AI检测两边通过AXI总线交换坐标和模板数据效果比纯FPGA方案稳健太多。这些扩展方向都建立在SAD模板匹配这个基础上所以把基础做扎实后面的路就会很顺。我在最后想分享的一点心得体会是做FPGA算法加速千万不要一上来就钻代码细节。先把算法确定好画出数据流图估算好计算量和资源量再启动编码。中间每一步都用仿真实测去验证能省下大量的联调时间。SAD这个项目看上去不大但它完整覆盖了图像采集、缓存管理、并行阵列设计、状态机控制、后处理滤波和上位机交互做完之后再看其他图像处理算法——不管是滤波、边缘检测还是光流——思路都会清晰很多。
返回列表