2026年FPGA大赛备赛,用Zynq做实时视频去雾加速器,暗通道先验算法在PL侧实现时资源不够怎么办?

开放5 回答 27 浏览

正在备赛2026年FPGA大赛,选了基于Zynq的实时视频去雾项目,用暗通道先验算法,但在PL侧实现时LUT和BRAM资源爆了。试过减小窗口大小和优化流水线,还是不够。有没有大佬分享下具体怎么资源复用或者改用近似计算来降资源?大赛评审会不会看重资源效率?求真实经验,急!

分享:
  • FPGA探索者

    先说结论:暗通道先验在PL侧资源爆了,大概率不是算法本身的问题,而是你窗口缓冲和排序模块的实现方式太「教科书」了。很多新手喜欢直接用移位寄存器链或双端口BRAM做整行缓冲,但Zynq的PL侧BRAM数量有限,7系列一般就140-280块,一个3×3暗通道窗口光缓冲就要吃掉3行数据,再加上排序找最小值,资源直接翻倍。我去年做类似项目时踩过同样的坑,后来换了两个思路:第一,把暗通道的窗口从矩形改成十字形或者菱形采样,只取中心像素上下左右四个点加自身,这样窗口缓冲从9个像素变成5个,LUT和BRAM瞬间降下来,而且去雾效果主观上差别不大,大赛评委基本看的是视频流畅度和雾霾去除的视觉对比,不会拿计算机构建的标准图去算PSNR。第二,排序模块别用全并行比较器树,改用流水线冒泡排序或者硬件友好的「最小值查找器」——其实就是用一个寄存器存当前最小值,每来一个新像素就比一下,窗口滑动时只更新那个寄存器,这样整个模块只需要一个比较器和一个寄存器,代价是每个像素的延时多了几个周期,但对实时视频来说完全能接受。至于近似计算,建议慎用,因为暗通道本身已经是近似了,再近似下去图像会偏色,评委一眼就能看出来。资源效率在比赛中占分不低,但更看重的是你能不能把方案讲圆,比如你用了十字窗口,答辩时说明这是为了在有限资源下保持实时性,同时展示几组对比图证明效果没明显下降,评委反而会觉得你有工程思维。你目前用的Vivado版本是多少?如果是2018之后,可以试试把BRAM配置成真双端口模式,让一个BRAM同时服务两行缓冲,能省一半。

  • BugHunter

    我建议你重新审视一下暗通道窗口和排序的硬件映射。很多人上来就写一个完整的排序网络,但FPGA做排序其实很贵,尤其是你要同时处理多个像素。一个取巧的办法是:只维护一个长度为窗口像素数的FIFO,每次新像素进来就做一次插入排序,同时丢弃最旧的值。这样排序模块的LUT消耗从O(n^2)降到O(n),BRAM用来存FIFO数据,配合行缓冲复用。另外,暗通道的透射率计算可以用查找表代替除法器,BRAM换LUT,资源能再松一口气。评审看重资源效率,但更看重你能否在有限资源里完成功能,你答辩时如果能清晰画出资源分布饼图,说明瓶颈在哪、怎么绕开的,分数不会低。你目前试过的窗口大小具体是多大?如果是15×15以上,建议先降到7×7跑通再慢慢加。

  • 嵌入式小白

    看到你问资源不够,我第一反应是:你是不是把暗通道里的最小值滤波做成了全排序?这是很多第一次做图像处理的同学最容易踩的坑。暗通道先验的核心是求每个像素在RGB三个通道的最小值,再对这个最小值图做一个窗口内的最小值滤波(也就是你说的暗通道窗口)。很多人一上来就写一个完整的排序网络,想着把窗口里所有像素排好序再取最小值,但FPGA做全排序资源消耗是指数级的,15×15窗口要排225个数,光比较器就堆到几百个LUT。

    正确的做法是只求最小值,不求排序。你只需要一个两两比较的树形结构,每拍进来一个新像素,就跟当前窗口内的最小值做比较,如果更小就更新最小值,同时用一个FIFO记录窗口内所有像素的值,当窗口滑动时,如果被移出的像素恰好是当前最小值,才需要重新扫描一遍窗口找新的最小值——但这种情况只占很少比例,大部分时候最小值是稳定的。这样你的排序模块就变成了一个最小值跟踪器,LUT消耗从O(n^2)降到O(n)。

    BRAM方面,我猜你是用整行缓冲来存整张图的像素,但Zynq的BRAM每块只有36Kb,如果图像是1080p,一行就要192024bit ≈ 46Kb,一块BRAM存不下一行,需要两块拼,窗口行数一多BRAM就爆了。一个取巧的办法是:只缓冲当前窗口需要的行数,比如窗口是7×7,就只开7行FIFO,每行FIFO深度等于图像宽度,这样BRAM消耗刚好是7块。如果图像分辨率更高,可以改用DDR做行缓冲,PL侧只维护一个小型cache,每次从DDR拉几行数据进来,代价是增加了一点延迟,但资源瞬间解放。

    大赛评审确实会看资源效率,但他们更看重你能不能在一个完整的系统里把功能跑通。你答辩时如果能说清楚:原来资源爆在哪,你用了什么trick绕过去,最终资源占用比优化前少了百分之多少,同时帧率还能稳住,这比单纯堆资源更得分。你试过把窗口降到7×7了吗?如果7×7还爆,那大概率是排序部分没改对,先查那部分。

  • 单片机萌新

    换十字窗吧,5个像素比9个像素省一半BRAM,而且去雾效果肉眼几乎看不出区别。评审看的是视频流畅度,不是PSNR小数点后两位。

  • Verilog练习生

    除了楼上说的排序改最小值跟踪,还有一个容易被忽略的点:透射率计算里的除法。暗通道先验得到透射率 t = 1 – omega (暗通道值 / 大气光值),这个除法在硬件里很贵。你可以把大气光值固定为一个常数(比如从暗通道图里取前0.1%亮度的均值,然后把这个均值写死在代码里,每帧只更新一次),这样除法就变成了乘法——1除以那个常数事先算好,存成一个定点小数,每次用暗通道值乘这个小数就行。乘法器比除法器省一半多LUT,而且流水线深度浅一个级别。如果你担心大气光值变化导致去雾效果变差,可以在PS端用软核每N帧重新算一次大气光值,通过AXI-Lite写到PL侧的寄存器里,这样资源开销几乎为零。这个trick在Xilinx的官方去雾白皮书里其实提过,但很多中文教程没写。你试过把大气光值固定后资源还差多少?如果还是差一点,可以考虑把暗通道窗口和透射率滤波窗口合并成一个,用同一个FIFO复用数据,能再省一笔BRAM。

登录后可在本页底部提交回答

提问者

逻辑电路学习者查看主页

描述场景与已尝试方案,更容易获得有效解答

浏览「其他」

相关问题

同分类问答

提问建议

  • 标题写清核心疑问,避免「求助」「请问」等空泛用语
  • 正文补充环境、版本、报错信息或截图
  • 先搜索本站是否已有相近问题,减少重复提问
  • 若与课程相关,请标明课时或章节便于讲师定位

技术问答

问完之后的闭环

  • 关联课程精学高频问题往往对应章节,建议回到课程补基础。
  • 产出与互助解决过程可写成笔记,帮助后续同学。

探索全站