
FPGA在做滑窗滤波的时候,缓存多行数据,选取以当前像素中心的窗口与滤波算子做卷积。这个是常见做法,了解到横向 + 纵向依次一维卷积,可以减少运算量。
先沿水平方向做一维卷积,再沿竖直方向做一维卷积,等价于:可分离卷积(separable convolution);只有当二维核是可分离核时,它才和直接二维滑窗卷积结果完全一样;否则二者输出不同。
方案1 :横向一维卷积 → 纵向一维卷积(可分离卷积) 如果二维核 K 可以拆成外积: 流程:
当且仅当二维卷积核可分离,横纵一维卷积才相当于二维滑窗卷积
绝大多数任意二维核(任意纹理模板、Laplacian、自定义不规则核)不能写成两个一维向量外积。
例如中值滤波、双边滤波、NLMeans、最大值滤波 此时 “先横后竖一维卷积” 是另一个滤波器,不等于直接二维滑窗。
方案 2:标准二维滑窗卷积 在图像上滑动一个二维窗口,假设滑窗大小3x3,当前像素进来,缓存两行数据,第三行数据流入,第二行数据为中心的窗口内像素与二维核逐点相乘、累加,输出:
原始图:

滑窗滤波图:

假设:图像分辨率H\times W,一维核长度 k;对应二维核 (k\times k),步长 1,same 填充。
每个输出点需要 (k^2k2k^2k2) 次乘法,全图需要O(HWk^2)O(H∗W∗k2)O(HWk^2)O(H∗W∗k2)次乘法
每行一维卷积 O(Wk),一共 H 行;然后每列一维卷积 O(Hk),一共 W 列 O(HWk + WHk) = O(2HWk)
当 k 比较大时消耗资源差距巨大
在纵向的一维卷积涉及到纵向滤波窗口的设定,可以分为全帧缓存、分块缓存等方案,全帧缓存延迟一帧时间。
如果系统对端到端延迟要求苛刻(例如激光、伺服、视觉闭环),哪怕可分离卷积时序更好,很多时候依然宁愿用二维滑窗;除非用 tiling 把延迟压到指标内。
流程:
延迟:
从第一个输入像素进入,到第一个有效输出像素出来:差不多是 1 帧的时间;
很多离线处理、对 latency 不敏感的 ISP 可以接受;但如果是实时预览、闭环控制、高速视觉跟踪,这个延迟往往不能接受。