今年秋招面了几家AI芯片公司,都被问到用Verilog实现实时视频去雾加速器,要支持AXI4-Stream接口。我知道暗通道先验和导向滤波是核心算法,但怎么在FPGA上实现流水线?比如透射率估计、大气光值计算、导向滤波这些模块,如何用行缓存和双端口BRAM来减少延迟?面试官还追问了怎么避免暗通道先验中最小值滤波的硬件开销,求大佬指点具体设计思路和资源优化技巧。
2026年,FPGA工程师校招面试被问如何用Verilog实现一个支持AXI4-Stream的实时视频去雾加速器,怎么从暗通道先验和导向滤波角度设计流水线?
提问
回答 8

暗通道先验里那个最小值滤波,面试官其实是想听你怎么用行缓存做滑动窗口,而不是真让你算一堆比较器。常见做法是开一个窗口大小的行缓存再加一个排序网络,但更省资源的是只维护窗口内的最小值缓存——每来一个新像素,比较新值和当前最小值,如果新值更小就替换,同时记录最小值在窗口内的位置,等它移出窗口时再重新扫描窗口计算新最小值。这样能省掉大量比较器。透射率估计和导向滤波之间的数据流,可以共用同一组行缓存,别每个模块都独立开BRAM。你追问一下面试官,他更关心的是吞吐率还是面积?不同取舍下流水线深度差很多。

我说说去年校招准备这个题目时的实际踩坑经验吧,希望能帮你少走弯路。面试官问AXI4-Stream接口,其实考察的重点不是算法本身,而是你怎么把算法拆成可流水的硬件阶段,以及怎么处理跨时钟域和数据依赖。暗通道先验的核心是两次最小值滤波:一次在局部窗口内求暗通道图,另一次在整帧图像上求大气光值。大气光值那个全局最小值,千万别傻傻地等整帧存完再算,那就违背了AXI-Stream实时流的要求。正确做法是在第一遍扫描时就维护一个全局最小值寄存器,每行结束时更新一次,等帧同步信号来了就锁存,这样大气光值只比像素数据晚几行就出来了,几乎不增加延迟。导向滤波那块是资源大头,尤其是均值滤波要用box filter。我试过用两套行缓存分别算I和p的局部均值,然后共用同一个窗口累加器,BRAM能省一半。但面试官更想听你怎么处理边界像素——如果不用补零,透射率图边缘会有黑边,你可以在FIR滤波器系数里做截断处理,或者在行缓存两端留出冗余列。另外透射率估计和导向滤波之间的数据流,可以用乒乓BRAM做双缓冲,这样两个模块能同时工作,上一帧做导向滤波时下一帧已经在算暗通道了。当时面试官问我怎么避免最小值滤波的硬件开销,我说可以用形态学腐蚀的快速算法,但他说更希望听到用行缓存加双端口BRAM做滑动窗口的工程优化。个人感觉,面试官其实在考察你对BRAM读写时序的理解,以及你能不能把图像处理中的行缓存概念迁移到视频流加速器里。你目前在用哪个系列的FPGA?不同器件对BRAM的配置方式会影响你的流水线深度设计。

从面试官的角度说一个常被忽略的点:透射率估计模块和导向滤波模块之间的数据位宽匹配。很多同学只盯着算法流水线,结果在仿真时才发现暗通道输出的透射率是8位定点数,而导向滤波期望的输入是带小数位的定点数,中间没做截位或饱和处理,导致滤波结果全错。正确做法是在两个模块之间加一个可配置的移位截位单元,用状态机控制是直通还是缩放。另外大气光值计算那块,如果你用全局最大值而非最小值(因为暗通道先验里大气光是从暗通道图取最亮的点),面试官可能会追问:你确定是最大值吗?这里有个经典陷阱——暗通道先验原文里大气光是从暗通道图中取前0.1%最亮像素的均值,而不是简单取全局最大。如果你直接取最大值,遇到白色物体就会误判。面试官追问这个细节,是在看你有没有读过原始论文。建议你在设计文档里注明你是用近似法还是精确法,并说明近似法的误差边界。一个小技巧:透射率图可以用下采样后的低分辨率版本做导向滤波,输出时再上采样回原分辨率,这样导向滤波的计算量能降到原来的四分之一,视觉质量损失肉眼几乎不可见。不过面试官可能会反问你怎么保证AXI-Stream的帧率匹配,这时候你可以说用双帧缓冲加FIFO做速率匹配。你目前是卡在算法理解上还是RTL实现上?不同阶段准备重点不太一样。

面试官问这个其实是想听你怎么在行缓存和双端口BRAM之间做权衡。暗通道先验的核心是两次最小值滤波,别在透射率估计那块用排序网络,太费LUT了,维护一个滑动窗口内的最小值缓存加位置记录就够用。你提到AXI-Stream接口,那大气光值计算得在第一帧扫描时同步更新,别等整帧结束再算。追问一下,你目标器件是7系列还是UltraScale?BRAM数量差挺多的。

个人感觉你被追问最小值滤波硬件开销,说明面试官在考察你会不会用近似替代。暗通道先验原文里那个局部最小值滤波,严格实现要开一个尺寸为15×15甚至更大的滑动窗口,每个像素都得做225次比较,在FPGA上纯用比较器阵列面积直接爆炸。常见做法是用两个一维的最小值滤波串联,先对每行做水平方向的最小值,再对结果做垂直方向的最小值,这样比较器数量从N^2降到2N。更激进的优化是直接用数学形态学里的腐蚀操作近似,用3×3或5×5的菱形结构元素代替矩形窗口,虽然暗通道估计会偏亮一点,但透射率误差在5%以内,人眼基本看不出区别。面试官如果追问误差边界,你就说这个近似会导致透射率偏大,最终复原图像亮度偏高,但可以通过在透射率估计后加一个很小的减法常数来校准。另外你提到导向滤波,其实如果不是追求极致质量,用快速导向滤波或box filter替代也能省大量除法器,面试时主动提这个取舍会让面试官觉得你见过实际工程。

说一个面试官可能不会明说但实际特别看重的点:透射率估计和导向滤波之间的数据位宽匹配。很多人的设计里暗通道输出透射率是8位定点数,但导向滤波期望的是带小数位的定点数,中间没做截位或饱和处理,仿真时滤波结果全是错的。正确做法是在两个模块之间加一个可配置的移位截位单元,用状态机控制是直通还是缩放。还有大气光值计算那块,面试官可能会追问你取的是暗通道图的全局最大值还是前0.1%最亮像素均值,这个细节能看出你读没读过原始论文。建议你在设计文档里注明你用的是近似法还是精确法,并说明近似法的误差边界,面试官会认为你有工程文档意识。

说实话,面试官问AXI4-Stream实时视频去雾,最核心的坑不在算法本身,而在你如何处理帧与帧之间的数据依赖。很多同学把暗通道先验的流程背得很熟,但一追问就露馅:大气光值计算到底是在当前帧算还是用上一帧的?正确答案是,严格来说应该在当前帧内完成全图扫描再算,但这违反了AXI-Stream的实时性要求——你不可能等到帧尾再输出第一个像素。工程妥协是在上一帧结束时锁存大气光值,当前帧直接用,代价是场景突变时会有几帧的滞后,但人眼基本不敏感。面试官追问这个的点在于,你有没有意识到硬件实时系统和软件仿真的本质区别:软件可以等整帧数据到位再算,而硬件必须假设数据是无穷流,所有全局量都得用滑动或缓冲方式近似。另外,透射率估计那块的导向滤波,千万别试图用浮点,全部转成定点数,位宽分配优先给透射率小数部分,整数部分4位就够了,因为透射率范围只在0到1之间。还有一点,面试官提到行缓存和双端口BRAM,其实是在考你二维滑动窗口的边界处理——窗口覆盖到图像边缘时你是补零还是截断,这直接影响边缘去雾效果。我个人建议用截断并增加一个很小的固定偏移量,避免边缘透射率偏大导致光晕。你准备这个题,别只看论文里的公式,去搜几个开源RTL实现,看看人家是怎么用状态机把暗通道计算、大气光估计、透射率求精三个阶段串成三级流水线的,面试时能画出流水线阶段划分图比背公式加分得多。顺便问一句,你目前是用Vivado的IP还是纯手写RTL?这决定了你箱子里可以带多少资源库。

面试官问这个,其实就想听两个词:行缓存和双端口BRAM。最小值滤波别用排序网络,维护一个窗口缓存加位置记录就能省80%的LUT。大气光值取上一帧的,别在实时流里等整帧。导向滤波用定点数,小数位给够8位就行。你要是能把这三个点说清楚,比背一整段论文加分。
发表回答
登录后可在本页底部提交回答
