资讯动态

基于FPGA的无人机实时车辆检测:PWGH+SVM硬件实现与优化

发布时间:2026/8/7 14:19:58 来源:尧图企业网站定制
1. 项目缘起当无人机需要一双“看得更清”的眼睛最近在做一个挺有意思的私人项目核心目标很简单让一架普通的消费级无人机能在飞行的过程中实时、准确地识别出地面上的车辆。听起来像是计算机视觉的常规操作对吧但难点在于我不想依赖一块高性能的嵌入式GPU或者把视频流回传到地面站用服务器处理。我希望所有的识别运算都直接在无人机搭载的一块小小的FPGA现场可编程门阵列上完成实现真正的端侧实时处理。为什么非得是FPGA这源于一个很实际的工程需求。无人机平台对功耗、重量和实时性有着近乎苛刻的要求。用通用处理器CPU跑复杂的视觉算法功耗和散热都是大问题用GPU虽然算力强但功耗和体积往往超标。FPGA的优势就在于它能通过硬件电路直接“固化”算法流程用并行流水线的方式处理数据在达到特定计算性能时其能效比远高于通用处理器。简单来说就是“专事专办”用定制的硬件电路去高效完成固定的任务——比如我们这里的车辆检测。这个项目的技术核心我选择了一个相对经典但有效的组合PWGHPyramid Weighted Gradient HOG金字塔加权梯度方向直方图特征提取器搭配SVM支持向量机分类器。PWGH可以看作是传统HOG特征的增强版通过引入图像金字塔和多尺度梯度加权能更好地捕捉车辆在不同尺度、不同视角下的轮廓和纹理特征尤其适合无人机这种俯拍、尺度变化大的场景。而SVM作为一个成熟的二分类器这里是“车”与“非车”在特征维度适中、样本量足够的情况下依然能提供非常不错的分类精度和泛化能力。所以整个项目的挑战就变成了如何将这个PWGHSVM的软件算法高效地“映射”到FPGA这块硬件画布上并针对硬件特性进行深度优化最终在有限的资源逻辑单元、内存带宽、功耗预算内跑出满足实时性要求的性能。这不仅仅是一个算法实现更是一次从软件思维到硬件思维的跨界实践。2. PWGHSVM算法核心为何选择这个“老兵”组合在开始动手写Verilog代码之前我们必须彻底吃透要实现的算法。PWGHSVM这个组合在今天看来可能不如各种深度学习模型“时髦”但在资源受限的嵌入式视觉领域尤其是需要确定性延迟和低功耗的场景它依然有独特的价值。2.1 PWGH特征提取从图像到数字指纹PWGH的全过程可以分解为以下几个关键步骤理解每一步的数学和物理意义对后续的硬件实现至关重要。第一步图像预处理与金字塔构建无人机传回的图像通常是RGB格式。我们首先将其转换为灰度图这一步在硬件上就是一个简单的加权求和Gray 0.299*R 0.587*G 0.114*B。接着为了应对车辆远近带来的尺度变化我们需要构建图像金字塔。通常我会做2-3层金字塔例如原图、1/2下采样、1/4下采样。在硬件实现时下采样不能简单用软件里的双线性插值那样计算量太大。我采用的是最直接的隔点采样或者配合一个简单的[1, 2, 1]滤波核后再采样在保证一定抗混叠效果的同时硬件开销极小。注意金字塔层数的选择是精度和速度的权衡。层数多小车辆检出率高但计算量呈倍数增长。对于道路监控场景2层金字塔原图和半分辨率通常是个不错的起点。第二步计算梯度幅值与方向这是HOG类特征的核心。对于金字塔每一层的灰度图像我们需要计算每个像素点的梯度。在软件中常用Sobel算子[-1, 0, 1]及其转置。在FPGA里我们可以利用其流水线优势设计一个专门的梯度计算模块。水平梯度Gx用当前像素右侧像素值减去左侧像素值。这可以通过一个3像素宽的滑动窗口和两个减法器实现。垂直梯度Gy用当前像素下方像素值减去上方像素值。幅值MM sqrt(Gx^2 Gy^2)。在硬件中直接开方运算代价很高我通常用近似公式M ≈ |Gx| |Gy|或者用max(|Gx|, |Gy|) 0.5*min(|Gx|, |Gy|)精度损失在可接受范围内但资源节省巨大。方向θθ arctan(Gy / Gx)范围在0~180度因为梯度方向无关正负。硬件实现arctan是个难点。我采用了查找表LUT法或CORDIC算法。对于PWGH我们通常将方向量化为9个区间每20度一个区间因此可以直接根据Gx和Gy的比值通过比较器电路确定所属区间完全避开复杂的浮点运算。第三步构建加权梯度直方图Cell内将图像划分成一个个小的单元格Cell例如8x8像素。对于Cell内的每一个像素根据其梯度方向θ属于9个区间中的哪一个将其梯度幅值M作为权重累加到对应的方向区间直方柱上。这就是一个Cell的梯度方向直方图。第四步区块归一化与“金字塔加权”传统的HOG会将相邻的2x2个Cell组合成一个区块Block并对区块内的所有直方图向量进行归一化如L2-Hys以增强光照不变性。PWGH在这里引入了“加权”思想对于金字塔中不同尺度的图像其Cell直方图在最终拼接前会被赋予不同的权重。通常分辨率更高的层细节更丰富权重更大。例如设定原图层权重为1.0半分辨率层权重为0.7。这个加权过程在硬件上就是一次乘法累加。第五步特征向量拼接将所有金字塔层、所有区块的归一化并加权后的直方图向量按顺序拼接成一个一维的长向量这就是最终用于描述整张图像或图像中某个候选窗口的PWGH特征向量。对于一个640x480的图像划分Cell和Block后特征维度可能在几千左右。这一步在硬件上就是数据的搬运和重组。2.2 SVM分类器从特征到决策得到PWGH特征向量后就要交给SVM来判断“是不是车”。一个线性SVM分类器的决策函数是f(x) sign( w·x b )其中x是我们的PWGH特征向量w是训练得到的权重向量b是偏置项sign是符号函数输出1代表“是车”-1代表“不是车”。在硬件上实现SVM推理核心就是计算向量点积w·x。这本质上是一系列乘积累加MAC运算。FPGA非常擅长做这种规整的并行计算。我们可以设计一个处理单元PE同时进行多个特征维度与对应权重的乘法然后求和最后加上偏置b与0比较得到结果。这里的关键在于模型量化。软件中训练的w和b通常是32位浮点数。直接搬到FPGA上会消耗大量的DSP乘法器和寄存器资源。我必须将权重和特征值量化到较低的位宽例如8位整数INT8或甚至4位整数。这需要在训练后对模型进行量化感知训练或后训练量化以最小化精度损失。在我的实现中我将PWGH特征值缩放到0-2558位权重也量化为8位这样一次乘法就是8bit*8bit结果用16-32位累加最终在精度和资源消耗间取得了很好的平衡。3. FPGA系统架构设计打造一条高效的视觉流水线把算法“翻译”成硬件首先需要规划一个清晰的系统架构。我的目标是在一块中等规模的FPGA比如Xilinx Artix-7系列上实现整个系统。下图展示了我设计的顶层模块框图----------------------- | 视频输入接口 | | (如DVP, MIPI CSI) | ---------------------- | 视频流 (RGB/YUV) v ---------------------- | 图像预处理模块 | | (灰度化金字塔生成) | ---------------------- | 多尺度灰度图流 v ---------------------- | PWGH特征提取引擎 | | (梯度直方图归一化) | ---------------------- | 特征向量流 v ---------------------- | SVM分类器核 | | (定点MAC运算单元) | ---------------------- | 判决结果 (是车/非车) v ---------------------- | 结果输出与标记 | | (如生成带框的视频流) | -----------------------图像预处理模块这个模块负责接收无人机摄像头传来的原始视频流。我假设输入是RGB格式通过一个流水线结构的灰度化单元将其转换为灰度图。同时这个模块内部包含一个下行采样单元同步生成金字塔的下一层图像。这里采用了双缓冲Ping-Pong Buffer机制在计算当前帧特征时下一帧的图像已经开始接收和预处理充分隐藏数据搬运的延迟。PWGH特征提取引擎这是最复杂也是最重要的部分。我将其设计为一个高度流水线化的结构。梯度计算流水线输入是灰度图像像素流输出是同步的梯度幅值和方向流。我实例化了多个相同的处理单元并行处理不同金字塔层的图像数据。直方图累加单元这是难点。传统软件是等一个Cell的所有像素都处理完再统计直方图这在硬件上会导致巨大的存储和延迟。我采用了“流式直方图”设计。我维护着当前行和上一行相关Cell的直方图缓冲区。当像素流过时根据其坐标实时更新对应Cell的9个方向区间的累加值。这需要精细的地址生成和缓冲区管理逻辑。归一化与加权单元当检测到一个Block的所有Cell数据就绪后触发归一化计算。我使用了简化的L2范数计算并为了避免除法采用了乘以倒数近似值的方法。加权操作则是在不同层的特征向量输出前乘以一个固定的系数。SVM分类器核由于PWGH特征向量维度较高完全并行计算所有点积需要巨量乘法器。我采用了折中的方案设计一个具有N个并行MAC单元的处理核N根据FPGA的DSP数量决定比如16或32。将特征向量和权重向量从片外DDR内存或片内BRAM中分块读取送入这个处理核进行循环计算。通过精心设计数据调度可以掩盖内存访问延迟使计算单元保持忙碌。全局存储器与数据流FPGA片内存储资源BRAM非常宝贵。我的策略是梯度计算中的行缓存、直方图累加用的Cell缓冲区这些需要高速访问的小容量数据放在BRAM中。而完整的图像帧、金字塔图像、以及SVM的大权重向量则存放在片外的DDR3 SDRAM中。通过AXI总线主控模块以突发传输的方式高效搬运数据确保特征提取引擎和SVM核“饿不着”。4. 关键硬件优化策略榨干FPGA的每一份性能在FPGA上做视觉算法不能只是把软件逻辑照搬过来。必须针对硬件特性进行深度优化这是项目成败的关键。4.1 定点量化与精度权衡如前所述全浮点运算在FPGA上是奢侈的。我全程采用定点数运算。像素与梯度灰度像素和梯度值用8位无符号整数0-255和8位有符号整数-128~127表示。直方图累加Cell内梯度幅值累加可能会比较大我用16位无符号整数作为累加器。归一化与权重归一化因子和金字塔权重我用Q格式的定点数表示例如Q1.151位整数15位小数。这样乘法还是整数乘法只是需要对结果进行截位或舍入。SVM计算特征值和权重都是8位整数乘法结果为16位累加器用32位防止溢出。确定位宽后必须在MATLAB或Python中建立定点模型与浮点模型的结果进行对比确保在大量测试样本上的误差在可接受范围内例如分类准确率下降不超过2%。这是一个反复迭代的过程。4.2 流水线与并行化设计这是提升吞吐量的不二法门。模块内流水在PWGH引擎内部梯度计算、直方图累加、区块归一化被设计成多级流水线。当前像素在第二级流水线处理时下一个像素已经进入第一级。理想情况下每个时钟周期都能吞入一个像素吐出一个像素的处理结果对于特征提取阶段。数据级并行对于SVM的点积运算我实例化了16个并行的乘法器一次可以处理16对特征-权重。同时由于图像金字塔的存在不同尺度的特征提取本身也是可以并行进行的我为此复制了多套梯度计算单元共享同一套控制逻辑和存储器接口。任务级并行利用FPGA的可重配置性当一帧图像的特征提取完成后SVM分类器核开始工作。此时图像预处理模块和PWGH引擎已经开始处理下一帧图像。形成了“预处理-特征提取-分类”的宏流水线实现了帧级并行。4.3 存储器访问优化存储器墙是性能瓶颈。数据复用与缓存在计算梯度时一个3x3窗口需要访问9个像素。我设计了行缓冲区Line Buffer缓存前两行的像素使得每个时钟周期窗口都能滑动到下一个位置而无需反复访问慢速的片外内存。突发传输与数据对齐通过AXI4总线访问DDR时一定要使用突发Burst传输模式将多个连续的数据打包一次传输极大提高总线利用率。并且确保访问地址是对齐的通常是64字节边界。BRAM分区与双端口利用将大的BRAM划分为多个小的双端口RAM。例如直方图累加单元中9个方向区间对应9个累加器。我可以将其放在9个独立的双端口BRAM中这样在一个周期内可以同时读取和更新所有9个值避免了访问冲突。4.4 资源利用与时序收敛DSP高效利用DSP切片是进行乘加运算的宝贵资源。我确保所有的乘法操作都通过(* use_dsp48 “yes” *)等综合属性映射到DSP上而不是用逻辑单元LUT拼凑后者速度慢且耗资源多。逻辑折叠对于某些无法完全并行的循环操作比如某些控制逻辑采用逻辑折叠Time-multiplexing让同一套硬件资源在不同时间服务不同的数据以面积换速度。时序约束与流水线打拍在Vivado中设置合理的时钟周期约束比如100MHz。在长组合逻辑路径上比如多级加法器、复杂的条件判断果断插入寄存器进行打拍Pipeline将其分割成多个时钟周期完成这是保证时序收敛无建立/保持时间违例的最有效手段。我经常在数据通路上“插寄存器”直到时序报告全部变绿。5. 开发流程、仿真与板级调试实录有了架构和优化策略接下来就是具体的实现。我的开发环境是Vivado VSCode用VSCode写Verilog代码更舒服仿真工具主要用Vivado自带的仿真器和Modelsim。5.1 自顶向下的模块化实现我严格按照之前设计的架构图用Verilog HDL进行编码。每个主要模块如图像预处理、梯度计算、直方图累加等都是一个独立的module有清晰的输入输出接口。我遵循寄存器传输级RTL设计风格所有逻辑都是同步于时钟的。关键模块代码片段示例梯度计算module gradient_calc ( input wire clk, input wire rst_n, input wire [7:0] pixel_in, // 输入像素流 input wire pixel_valid, output reg [7:0] grad_mag, // 梯度幅值近似 output reg [3:0] grad_dir, // 梯度方向0-8 output reg grad_valid ); // 行缓冲区 reg [7:0] line_buf [0:1][0:IMAGE_WIDTH-1]; // 3x3窗口寄存器 reg [7:0] window [0:2][0:2]; always (posedge clk or negedge rst_n) begin if (!rst_n) begin // 初始化... end else if (pixel_valid) begin // 滑动窗口更新逻辑... window[0][0] window[0][1]; window[0][1] window[0][2]; window[0][2] line_buf[0][col1]; // ... 更新其他窗口位置 // 计算梯度 wire signed [8:0] gx {1‘b0, window[1][2]} - {1’b0, window[1][0]}; // 扩展一位防溢出 wire signed [8:0] gy {1‘b0, window[2][1]} - {1’b0, window[0][1]}; // 计算近似幅值和方向 wire [7:0] abs_gx (gx[8]) ? (~gx[7:0]1) : gx[7:0]; wire [7:0] abs_gy (gy[8]) ? (~gy[7:0]1) : gy[7:0]; grad_mag abs_gx abs_gy; // 近似计算 // 方向量化简化版根据gx, gy比值查表或比较 if (abs_gx abs_gy * 2) grad_dir (gx[8]) ? 4‘d0 : 4’d4; // 主要水平方向 else if (abs_gy abs_gx * 2) grad_dir (gy[8]) ? 4‘d2 : 4’d6; // 主要垂直方向 else begin // 对角线方向判断... end grad_valid 1‘b1; end else begin grad_valid 1’b0; end end endmodule5.2 分阶段仿真验证仿真必须循序渐进不能等全部写完再仿真。模块级仿真为每个子模块编写独立的测试平台Testbench用$readmemh从文件读入简单的测试图像如一个黑白方块验证其功能是否正确。比如梯度计算模块输入一个边缘明显的图案看输出的幅值和方向图是否符合预期。子系统仿真将图像预处理、PWGH引擎连起来仿真。输入一张小的测试图片比如64x64将最终生成的特征向量导出到文件与MATLAB黄金参考模型Golden Model的输出进行逐点对比误差必须在阈值内。带SVM的闭环仿真将SVM核集成进来输入一整张包含车辆和非车辆的图片验证最终输出的检测框位置是否正确。这里SVM的权重系数需要从训练好的模型中导入用$readmemh初始化到BRAM中。踩坑实录在仿真直方图累加模块时我最初忽略了边界Cell的处理。在图像边缘3x3的梯度窗口会越界。我必须在硬件逻辑中增加边界条件判断对越界位置的像素按0梯度处理否则会导致直方图统计错误进而影响检测精度。这个bug在模块级仿真中很容易被忽略直到集成测试时才暴露出来。5.3 板级调试与性能测试将综合、实现后的比特流文件下载到FPGA开发板我用的是一块带摄像头接口和DDR3的Artix-7板卡连接真实的无人机摄像头或播放视频文件的测试源。调试手段ILA集成逻辑分析仪这是Vivado的利器。我把关键信号如像素流控制信号、特征向量数据、SVM判决结果添加到ILA核中在硬件运行时实时抓取波形就像在板子上用逻辑分析仪一样可以精准定位数据流在哪里卡住、计算结果为何异常。VIO虚拟输入输出用于动态修改一些参数比如金字塔权重、SVM判决阈值无需重新编译工程就能测试不同参数下的效果。UART串口打印将一些统计信息如处理帧率、检测到的车辆数通过UART发送到PC端显示方便性能评估。性能测试结果 在100MHz的系统时钟下对于720p1280x72030fps的视频流经过优化后的设计可以达到处理延迟从一帧图像输入到输出检测结果约为3帧时间~100ms。这主要源于流水线填充和DDR访问延迟但对于无人机避障或跟踪来说这个延迟是可接受的。资源占用在Artix-7 XC7A100T上资源利用率大约为LUT 65% FF 40% BRAM 70% DSP 80%。这是一个比较紧张但可行的配置。功耗静态加动态功耗约2W远低于同等性能的嵌入式GPU方案。检测精度在自建的小型无人机俯拍车辆数据集上准确率mAP达到了约85%比未硬件优化的纯软件版本在ARM Cortex-A9上运行快20倍以上精度损失约3%。6. 项目总结与未来演进思考回顾整个项目从算法选型、架构设计、RTL实现到优化调试是一次完整的软硬件协同设计实践。PWGHSVM这个经典组合在FPGA的加持下展现出了在特定场景下资源受限、要求确定性和低功耗的强大生命力。几点核心体会算法简化是硬件友好的前提在算法设计阶段就要考虑硬件实现的可行性。例如用幅值近似代替开方用方向区间比较代替arctan用定点数代替浮点数。这些简化在软件上可能微不足道但在硬件上能节省海量资源。数据流设计优于控制流设计FPGA擅长流水线。要尽可能将算法转化为规整的数据流Stream Processing模式避免复杂的、带分支的控制逻辑。我的PWGH引擎就是一个典型的数据流设计像素像水流一样经过各级处理单元。面积、速度、功耗的永恒三角FPGA设计就是在三者间做权衡。并行化提升速度但增加面积和功耗流水线提升吞吐量但增加延迟和寄存器开销降低数据位宽节省面积和功耗但可能损失精度。没有最优解只有最适合当前约束的平衡点。仿真与调试的时间可能远超编码时间尤其是涉及到复杂数据流和存储访问的模块编写完备的测试平台进行充分的仿真验证是保证项目成功的关键。硬件调试ILA是最后的手段但不是首选。未来可能的演进方向集成更先进的检测流程目前是滑动窗口分类器速度慢。未来可以尝试用FPGA实现候选区域生成网络如区域提议网络RPN的简化版或者直接实现轻量化的单阶段目标检测网络如YOLO的定点化版本。引入在线学习或自适应机制让SVM的分类器参数能在FPGA上根据当前环境进行微调适应不同的光照、天气条件。系统级优化将整个视觉处理系统与无人机的飞控系统更紧密地结合例如将检测结果直接用于视觉伺服控制实现真正的“感知-决策-控制”闭环。这个项目让我深刻体会到将算法植入硬件不仅仅是编程语言的转换更是思维模式的跨越。它要求开发者同时具备算法理解、硬件架构、电路时序等多方面的知识。当看到无人机基于自己设计的硬件电路实时地从空中锁定地面车辆时那种软硬件协同工作带来的确定性和效率是纯软件方案难以比拟的成就感。对于有志于嵌入式视觉或边缘AI的工程师来说掌握FPGA这类硬件加速技术无疑是打开了一扇新的大门。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价