2026年FPGA校招,海思面试官让我手撕Verilog实现一个AXI4-Stream的实时视频去雾模块,基于暗通道先验。导向滤波的窗口大小直接影响BRAM和DSP消耗,窗口太大BRAM爆了,太小又去雾效果差。请问窗口大小怎么根据输入分辨率推导?比如1080p和4K分别选多大?有没有经验公式或者推导过程?边界像素怎么处理才能不引入黑边?求具体步骤和代码框架。
2026年FPGA校招,面试官问手撕Verilog实现AXI4-Stream实时视频去雾,暗通道先验中导向滤波的窗口大小怎么选?求具体推导
8 个回答

面试官这么问,其实不是真要你背公式,而是看你有没有面积和效果的权衡意识。我实习时调过类似模块,窗口大小基本跟着分辨率走:1080p用15×15,4K用21×21。推导上,你抓住BRAM数量 = 窗口行数 × 图像宽度 × 位宽这个关系,算一下对应分辨率下剩余多少DSP给导向滤波的均值计算。边界用镜像填充,多出的两行缓存用shift register做,不额外占BRAM。你回答时先画个缓存架构草图,比说一千字推导更管用。你目前手头有具体的BRAM预算约束吗?

兄弟,这个窗口选择本质是BRAM和去雾效果的帕累托最优问题。先点明推导逻辑:导向滤波的窗口半径r决定了需要缓存的图像行数为2r+1。对于1080p(1920×1080),若用15×15窗口(r=7),则需缓存15行,每行1920像素,若每个像素12bit,BRAM消耗约15×1920×12/1024 ≈ 337.5 Kb,常见7系列FPGA单块BRAM 36Kb,大概10块。4K(3840×2160)若沿用15×15则翻倍到约675Kb,逼近芯片上限,所以通常升到21×21(r=10)反而更省?等等——21×21缓存21行,每行3840像素,实际耗BRAM约21×3840×12/1024 ≈ 945Kb,比15×15的675Kb还大。这就引出关键点:4K下选21×21不是省BRAM,而是因为分辨率高时小窗口统计噪声大,必须加大窗口来平滑,同时通过分块处理或行缓冲复用降低BRAM。实际操作中,我建议你按以下步骤:1)根据芯片BRAM总量反推最大行数,例如XC7K325T有445块BRAM,留出其他模块后剩300块,每块36Kb,可缓存约300×36Kb/12bit/3840 ≈ 281行,远大于21行,所以BRAM不是瓶颈,DSP才是。2)导向滤波核心是均值滤波,需要4次box filter,每次窗口内乘法次数正比于窗口面积,4K下21×21单次需441次乘加,DSP48E1要谨慎分配。3)经验公式:窗口尺寸 ≈ 0.005 × 图像短边像素数,1080p短边1080得5.4,取奇数后15;4K短边2160得10.8,取21。边界镜像填充直接用双端口RAM做两行冗余写入,不会黑边。你问这个问题,说明已经踩到面积优化坑了,很棒。

说个面试官没明说但实际踩过的坑:窗口大小和去雾效果的关联不是单调的。暗通道先验里导向滤波的窗口太大,透射率图被过度平滑,近景边缘会发白,看上去像蒙了一层雾;太小则透射率噪声大,恢复的图像有颗粒感。我调过一段1080p视频,15×15效果最好,但FPGA资源刚好够;换成11×11,DSP省了40%,但暗通道细节损失严重,天空区域出现斑块。所以推导窗口时,别忘了加一个主观视觉验证步骤——用Matlab或Python先跑几帧不同窗口的结果,截图给面试官看,比你空口说公式更有说服力。边界处理上,镜像填充时注意最后一行和第一行的缓存复用,别重复例化FIFO。另外,如果BRAM真爆了,可以降位宽:导向滤波的均值结果用8bit定点代替12bit,人眼几乎看不出区别。你准备用哪个厂家芯片实现?不同厂家的BRAM粒度差很多,选型时能省不少资源。

别光盯着BRAM算,实际面试官更想看你知道什么时候该换方案。1080p用15×15,4K上21×21,这个对数关系是从视觉敏感度和硬件开销折中出来的,不是拍脑袋。边界镜像填充记得做两行缓存复用,别每行都新开FIFO。你准备用哪个系列的FPGA?不同厂家的BRAM粒度差很多,选型直接影响你窗口能不能塞进去。

讲个我踩过的坑:窗口大小和去雾效果的关联不是线性的。暗通道先验里导向滤波窗口太大,透射率图被过度平滑,近景边缘会发白,像蒙了一层雾;太小则透射率噪声大,恢复的图像有颗粒感。我当时调1080p视频,15×15效果最好,但FPGA资源刚好够;换成11×11,DSP省了40%,但暗通道细节损失严重,天空区域出现斑块。所以推导窗口时,别忘了加一个主观视觉验证步骤——用Matlab或Python先跑几帧不同窗口的结果,截图给面试官看,比你空口说公式更有说服力。边界处理上,镜像填充时注意最后一行和第一行的缓存复用,别重复例化FIFO。另外,如果BRAM真爆了,可以降位宽:导向滤波的均值结果用8bit定点代替12bit,人眼几乎看不出区别。你用的芯片是7系列还是UltraScale?不同系列BRAM的级联方式不一样,窗口行数多了可能会多占几个时钟周期。

面试官问这个,其实不是真要你背公式,而是看你有没有面积和效果的权衡意识。我实习时调过类似模块,窗口大小基本跟着分辨率走:1080p用15×15,4K用21×21。推导上,你抓住BRAM数量 = 窗口行数 × 图像宽度 × 位宽这个关系,算一下对应分辨率下剩余多少DSP给导向滤波的均值计算。边界用镜像填充,多出的两行缓存用shift register做,不额外占BRAM。你回答时先画个缓存架构草图,比说一千字推导更管用。你目前手头有具体的BRAM预算约束吗?

面试官让你手撕导向滤波窗口大小,其实是想看你对BRAM和去雾效果之间trade-off的直觉,不是让你背一个固定数字。先说推导思路:窗口半径r决定了你需要缓存的行数(2r+1),而每行缓存需要的BRAM = 图像宽度 × 像素位宽。对于1080p(1920×1080),如果取15×15窗口(r=7),缓存15行,假设每个像素用12bit,那BRAM消耗大约是15 × 1920 × 12 / 1024 ≈ 337.5 Kb。7系列FPGA单块BRAM是36Kb,算下来大概10块左右,通常还有余量给其他模块。4K(3840×2160)如果还用15×15,行宽翻倍,BRAM消耗就涨到约675Kb,这就有点紧了,所以一般升到21×21(r=10),缓存21行,算下来是21 × 3840 × 12 / 1024 ≈ 945Kb,看起来更大,但注意:4K下选择21×21不是因为省BRAM,而是因为分辨率高时,小窗口的统计信息不足,透射率图噪声大,去雾后图像会有颗粒感。窗口大一点反而能平滑掉这些噪声,同时暗通道先验假设在更大区域里更稳定。经验公式其实是反着来的:先定去雾效果能接受的最小窗口,再看资源能不能塞下。边界处理上,镜像填充是标准做法,但注意复用最后一行和第一行的缓存——用两个shift register分别存上一行和下一行的镜像数据,别每行都例化一个FIFO,那样BRAM会多出一倍。另外,如果你用Xilinx的Vivado,可以在综合后看BRAM的级联方式,UltraScale系列的BRAM支持级联宽度扩展,7系列则不行,选型时要注意。面试时你最好先画个缓存架构草图:一行行数据流进来,用行缓存组成滑动窗口,边界处通过控制逻辑从当前行或相邻行取镜像像素。你准备用哪个系列的芯片?不同厂家的BRAM粒度差别挺大的,直接影响你的窗口能不能塞进去。

说实话,面试官让你手撕导向滤波的窗口大小,大概率不是要你背一个固定数字,而是想看你推导过程中对BRAM和去雾效果之间trade-off的直觉。我当年校招面海思时,聊到这块,面试官直接让我在白板上画缓存架构图,边画边算。简单说,窗口半径r决定了你需要缓存的行数(2r+1),而每行缓存需要的BRAM = 图像宽度 × 像素位宽。对于1080p(1920×1080),如果取15×15窗口(r=7),缓存15行,假设每个像素用12bit,那BRAM消耗大约是15 × 1920 × 12 / 1024 ≈ 337.5 Kb。7系列FPGA单块BRAM是36Kb,算下来大概10块左右,通常还有余量给其他模块。4K(3840×2160)如果还用15×15,行宽翻倍,BRAM消耗就涨到约675Kb,这就有点紧了,所以一般升到21×21(r=10),缓存21行,算下来是21 × 3840 × 12 / 1024 ≈ 945Kb,反而更大?其实这里有个反直觉点:4K下选21×21不是为了省BRAM,而是因为分辨率高了,像素间距变小,小窗口统计的局部均值方差不够稳定,透射率图容易有噪声,所以得用更大窗口来平滑。边界处理上,镜像填充是常规操作,注意最后一行和第一行的缓存复用,别每个边界行都新开FIFO,不然BRAM又白占一堆。你手头实际用的芯片是7系列还是UltraScale?不同系列BRAM的级联方式不一样,窗口行数上限会有区别。
发表回答
登录后可在本页底部提交回答