今年FPGA大赛想选高云FPGA做实时图像去雾,暗通道先验算法在PC上跑通了,但移植到FPGA上资源不够,特别是透射率计算那部分。有没有前辈用高云FPGA做过类似项目?求分享如何优化算法结构,把关键模块流水线化,以及高云IDE相比Vivado有哪些坑要注意?
2026年FPGA大赛,用高云FPGA做实时图像去雾,暗通道先验算法硬件加速怎么实现?
提问
回答 5

先讲最核心的约束:高云FPGA的LUT和DSP资源比Xilinx同等级芯片少很多,暗通道先验里透射率计算涉及大量排序和除法,直接搬PC代码肯定爆。我去年用高云GW2A-55做过类似去雾,说两个关键取舍。
透射率计算那块,别做全局排序求最小值。暗通道先验本质是局部最小值滤波,你可以改成滑窗比较器链加移位寄存器,窗口大小15×15以内,用BRAM缓存几行数据,每个时钟出一个窗口的最小值,这样流水线就打通了。排序器太费LUT,高云LUT6结构一用排序器面积直接翻倍。
另一个是除法问题。透射率公式里有除法,高云没有硬核除法器,用IP核或者自己写都会很慢。我的做法是把大气光值和透射率系数量化成定点数,查表代替除法,精度损失在可接受范围。
高云IDE有个坑:它的综合工具对流水线描述不敏感,你写always块里插寄存器可能被优化掉,必须手动在RTL里例化流水线寄存器模块,或者在综合属性里关掉寄存器合并。另外高云的PLL配置界面容易漏约束,建议仿真确认时钟相位没问题再上板。
你目前打算用哪款高云芯片?资源数大概多少?这会影响窗口大小和并行度的选择。

如果你已经在PC上跑通了算法,那说明你对暗通道先验的数学流程是清楚的。移植到FPGA遇到资源瓶颈,核心问题在于:PC上用的是浮点、排序、全局搜索,而FPGA硬加速必须改成定点、并行流、局部近似。我按一个实际可行的优化路径来拆解,你对照自己的设计看哪些能改。
第一步改数据通路。暗通道先验的第一步是取R/G/B三通道最小值,PC上按像素循环,FPGA上应该用一个三级比较树,每个时钟输入一个像素,输出该像素的三通道最小值,这样只需要几个比较器,不占BRAM。第二步是局部最小值滤波,这是资源大头。常见做法是开一个窗口缓存,比如15×15,需要缓存15行数据,每行宽度取决于图像宽度。高云的BRAM一般够用,但要注意:高云BRAM的读写时序跟Xilinx略有差异,读延迟多一拍,你写状态机时要对应调整握手信号。窗口内的最小值计算不要用排序网,用滑窗比较器链,每来一个新像素,只更新窗口内对应列的最小值,再取列最小值的最小值,这样整个模块的LUT消耗能控制在几百个以内。
透射率公式 t(x) = 1 – omega min_c ( min_y ( I_c(y) / A_c ) ),其中除法是瓶颈。两个技巧:一是把大气光值A_c固定,因为A_c只从天空区域取一次,可以提前算出1/A_c的定点倒数表;二是omega系数一般取0.95,可以预乘到倒数表里,这样除法变成一次乘法加一次移位。高云的DSP48单元够用的话,把乘法映射到DSP上,不占LUT。
还有个小细节:高云IDE默认的优化策略偏向面积优化,如果你追求实时性,需要在综合设置里把优化目标改成速度,并关掉寄存器共享。另外,高云的IP核生成器里没有现成的图像滤波核,你得手写行缓存控制器,建议用双口BRAM做乒乓缓存,避免帧间冲突。
你目前的图像分辨率是多少?如果是1080p,窗口大小和流水线深度可能需要进一步折中,比如把窗口缩小到11×11或者降低帧率要求。

看到你用高云做暗通道先验,我第一反应是:别急着把PC代码里的排序和除法照搬。高云的LUT和DSP资源比Vivado那套紧张不少,但它的BRAM配置挺灵活的,可以拿来缓存多行数据做滑窗。我建议你先把透射率计算里的全局最小值改成局部滑窗比较,窗口大小根据你的图像分辨率定,比如15×15,用移位寄存器和比较器链实现,每个时钟出一个最小值,这样流水线就打通了。高云IDE有个坑:它的综合工具对always块里插寄存器的流水线描述不太敏感,你在写Verilog时最好手动例化寄存器,别依赖工具自动推断,否则综合出来面积可能失控。另外,大气光值估算可以放到PC端预处理,或者用简单的最大值统计模块在FPGA上跑,别在透射率路径里做复杂除法。你目前图像分辨率是多少?如果低于1920×1080,BRAM缓存压力会小很多。

我去年用高云GW2A-55做过类似去雾,踩过不少坑,直接说几个关键取舍。暗通道先验移植到FPGA,核心瓶颈是透射率计算里的局部最小值滤波和除法。PC上你用的排序算法复杂度高,FPGA上必须改成滑窗比较器链加移位寄存器:比如窗口15×15,先缓存15行数据到BRAM,每行宽度等于图像宽度,然后用15个比较器链对每列做最小值,再在行方向上做比较,每个时钟输出一个窗口的最小值。这样资源消耗主要是BRAM和少量LUT,高云的BRAM读写时序跟Xilinx略有差异,读延迟多一拍,你写状态机时要对应调整握手信号,否则数据错位。除法那块,高云没有硬核除法器,用IP核会消耗大量LUT和延迟。我的做法是把大气光值量化成定点数,透射率公式里的分母用查表代替,精度损失在可接受范围内,表的大小根据你需要的透射率精度定,比如256个条目。高云IDE还有个坑:它的综合工具对时序约束支持比较弱,如果你不做显式的create_clock约束,工具可能把关键路径优化错,建议在sdc文件里明确声明时钟周期和输入输出延迟。你当前算法里透射率计算用了多少级流水线?如果超过5级,建议先压缩到3级以内,否则高云LUT的级联延迟容易造成时序违例。

看到你说资源不够,我第一反应是:你可能把PC上的排序和除法原封不动搬过来了。暗通道先验里最吃资源的就是透射率计算那一块,尤其是局部最小值滤波。PC上用排序,FPGA上必须改成滑窗比较器链,窗口大小根据你图像分辨率定,比如15×15,先缓存15行数据到BRAM,每行宽度等于图像宽度,然后用比较器链对每列做最小值,再在行方向上比较,每个时钟输出一个窗口的最小值。这样资源消耗主要是BRAM和少量LUT,高云的BRAM配置挺灵活的,但要注意读写时序跟Xilinx有差异,读延迟多一拍,你写状态机时要对应调整握手信号。除法那块,高云没有硬核除法器,用IP核会消耗大量LUT和延迟,我的做法是把大气光值量化成定点数,透射率公式里的分母用查表代替,精度损失在可接受范围内,表的大小根据你需要的透射率精度定,比如256个条目。另外,高云IDE有个坑:它的综合工具对always块里插寄存器的流水线描述不太敏感,你写Verilog时最好手动例化寄存器,别依赖工具自动推断,否则综合出来面积可能失控。你目前图像分辨率是多少?如果低于1920×1080,BRAM缓存压力会小很多,还可以考虑把大气光值估算放到PC端预处理,减少FPGA上的计算负担。
发表回答
登录后可在本页底部提交回答
