2026年FPGA大赛用Zynq做实时视频去雾,暗通道先验算法在PL侧BRAM不够怎么办?求具体优化方案

开放6 回答 31 浏览

今年FPGA大赛想做实时视频去雾,选了暗通道先验算法,在Zynq上实现时发现BRAM根本不够用,透射率估计和导向滤波那几步特别吃内存。有没有什么优化套路,比如分块计算、流水线复用或者改用行缓冲?求大佬给个具体方案,最好能控制在1080p30帧以内,BRAM占用降到80%以下。

分享:
  • 代码焊工

    我猜你八成是刚把论文里的暗通道原封不动搬上板子,才被BRAM干趴的。1080p30帧,窗口15×15的暗通道和导向滤波,按常规做法确实会把BRAM塞爆。核心思路就是分块和行缓冲配合,别想着存一帧完整图。暗通道那步,你可以用滑动窗口+局部最小值近似,每来一行数据就更新一个行缓存的局部最小值,窗口内只用比较器树,不用存整幅图。透射率估计同理,把最小值滤波拆成水平方向和垂直方向两次一维操作,中间只存一行中间结果。导向滤波更关键,很多人在这里直接上整帧协方差矩阵,那BRAM当然炸。改用滑动窗口算局部均值,系数窗口内复用,窗口滑过一行后只保留必要的累加值。这样下来,BRAM占用能压到60%左右,而且延迟只多几行。不过要注意,近似处理会带来轻微边缘模糊,比赛时评委如果拿原图对比可能扣分。你打算用纯PL还是加PS协同?如果PS能分担一部分系数计算,BRAM还能再省一点。

  • 芯片设计预备役

    既然目标是1080p30帧,先算一笔账:单帧1920×1080,15×15窗口的暗通道,如果老老实实存整帧的最小值图,光这一步就要192010808bit约2MB,Zynq上中等器件的BRAM总共也就几百KB,显然不现实。所以必须把算法从「帧级」降维到「行级」。我建议你走这条路:第一步,暗通道估计改用行缓冲+局部最小值滤波的流水线实现。具体说,用FIFO缓存15行数据,每来一个新像素,更新该像素所在15×15窗口内的最小值,这里可以用比较器树并行算出,结果只输出一列,这样你只需要存15行数据而非整帧。第二步,透射率估计里的最小值滤波同理,拆成水平和垂直两次,水平方向用行缓冲,垂直方向用列缓冲,中间结果只保留一行。第三步,导向滤波是耗BRAM大户,很多开源实现直接存整帧的均值图,必须改。我见过一种做法:把导向滤波的系数计算拆成滑动窗口内的局部累加,窗口大小固定,每滑过一个像素就更新一次累加和,这样只需要存窗口宽度的行缓冲,配合系数复用,BRAM占用能降到原来三分之一。整体下来,BRAM占用大概能控制在60-70%,帧率跑满30帧没问题。但有个坑要注意:这种分块近似会让去雾效果在某些边缘区域出现块状伪影,如果评委是搞图像处理的可能会看出来。建议你在暗通道估计那步,窗口大小从15×15缩到9×9或者11×11,效果损失不大但BRAM压力小很多。另外,如果你时间充裕,可以试试把透射率估计和导向滤波合并成一步,用联合双边滤波近似,省掉导向滤波那套复杂的均值计算。你目前是已经写了部分代码还是在方案选型阶段?如果还在选型,建议先搭一个行缓冲的仿真模型验证效果,别急着上板。

  • 面向百度

    BRAM不够就分块加行缓冲,别想着存整帧。暗通道和导向滤波都改成滑动窗口,一次只处理几行,BRAM占用能压到60%以下。去雾效果会稍微变差,但比赛够用了。

  • Git新手01

    你遇到的BRAM瓶颈,在1080p30帧的暗通道去雾实现里几乎是必然的。很多参赛者第一步就栽在「直接搬论文框图」上——论文里假设你有无限存储,但FPGA上每一比特BRAM都要精打细算。我的建议是彻底放弃帧级处理,转向行级流水线。暗通道那步,用15行行缓冲加滑动窗口局部最小值滤波,每来一个像素,用比较器树并行计算当前15×15窗口内的最小值,结果只输出一列,这样你只需要存15行数据而不是整帧。透射率估计里的最小值滤波,拆成水平方向和垂直方向两次一维操作,中间只保留一行中间结果。导向滤波是真正的BRAM大户,很多开源实现直接存整帧均值图,这必须改:改用滑动窗口算局部均值,系数在窗口内复用,窗口滑过一行后只保留必要的累加值。这套方案下来,BRAM占用能压到60%左右,延迟只多十几行。但有个代价:近似处理会带来轻微边缘模糊,比赛评委如果拿原图逐像素对比,可能会扣分。另外,你打算用纯PL实现还是配合PS做部分控制?如果纯PL,注意透射率估计里的除法运算要提前做查表简化,否则时序会崩。你目前用的是哪款Zynq?具体型号决定BRAM总量,优化空间差异很大。

  • Verilog代码新手

    BRAM不够就别硬存整帧,分块加行缓冲是标准解法。暗通道用滑动窗口,导向滤波改系数复用,80%以下不难。关键是你得接受画质轻微下降。

  • 电路学习中

    分块处理其实是最直观的思路,但很多人一上来就分得太细,导致块间拼接处出现明显伪影。我建议你换一个角度:不是把图像切成独立的小块,而是用重叠分块加双缓冲。具体说,把1080p图像按行分成若干条带,每条带宽度就是窗口高度15行,相邻条带之间重叠14行,这样每个条带内部可以独立计算暗通道和透射率,块间拼缝自然过渡。双缓冲机制让PL侧在处理当前条带时,DDR同时通过AXI-Steam预取下一个条带,流水线不中断。这个方案的优点是逻辑复杂度低,你不需要改动算法本身,只是把帧级计算降维到条带级,画质几乎无损。缺点是外部DDR带宽占用会上升,1080p30帧1920x1080x3x8bit约50MB/s,加上重叠数据后大约翻倍到100MB/s,Zynq的DDR带宽通常够用。你目前的外部存储用的是DDR3还是DDR4?如果是DDR3的话,注意控制突发长度和AXI总线位宽,避免带宽瓶颈。

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

提问者

EDA初学者查看主页

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

浏览「其他」

相关问题

同分类问答

提问建议

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

技术问答

问完之后的闭环

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

探索全站