频域滤波的快速实现是工程领域的里程碑。频域滤波最让工程师兴奋的原因来自于这个公式:
f(x)*g(y)<-->F(u)G(v)
这说明空间域中的复杂的卷积算子,变换到频域中就成了简单的乘法,这样不仅计算简单,而且工程上易于实现。在FFT和快速DCT(余弦变换)的数字实现之前,频域变换的计算是很头疼的事情,在计算效率上并不比普通卷积快多少;在FFT和快读DCT实现之后,频域信号处理几乎无处不在。
空间域滤波的算子可以变成频域滤波算子。假设当前图像尺寸为512x512,滤波算子大小为3x3,显然直接对滤波算子进行频域转换后的结果仍然为3x3,这是无法相乘的。这需要从定义出发来解释。
卷积的定义是:f(t)*g(t)= 如果f和g是周期不同的周期函数,那么我们要用0补全函数周期,保证补全后的函数f’和g’有相同的周期,然后再进行卷积;否则不能保证f和g函数在同一个周期内进行卷积,导致不同周期的滤波结果混淆起来。
回到原始的空间滤波上讲,平时我们的操作是遍历当前图形512x512的每个像素,用3x3的模板对当前像素领域进行卷积操作。其实这是简化后的操作,真正的操作其实是,构建512x512大小的卷积模板,其左上角3x3元素是执行空间域滤波操作的算子元素,剩下的元素全部为0,用这个512x512的卷积模板对图像进行二维卷积。由于除了3x3以外的元素都是0,所以我们实现的时候,只需要计算3x3模板范围的值,看起来就像只用3x3卷积模板对当前像素邻域做操作。
明白了512x512图像的空间滤波算子其实也是512x512大小之后,那么我们就可以实现从空间域滤波到频域滤波。构建一个512x512的滤波算子,把3x3模板参数放在算子左上角(放在不同位置会导致滤波结果变得奇怪,比如图像被循环位移),然后进行频域转换生成512x512的频域模板,将其与频域图像相乘(注意如果频域图像中心化,那么频域模板也要中心化),然后还原到空间域图像,就完成一次和空间域滤波结果相同的频域滤波。
频域滤波就完美无瑕了吗?当然不是。假设我的图像大小为512x512,灰度范围为0~255,那么每个像素只需要用1 byte表示,共512x512 bytes;进行频域滤波之后,我需要用两个float甚至double矩阵来表示频域图像的实部和虚部,这就需要512x512x4x2或者512x512x8x2 bytes,一下子内存消耗多了8~16倍;如果频域转换精度不够高的话,经过频域转换再还原到空间域的图像会有信号损失,而不会完全还原到原始图像。请注意,计算机常用的压缩算法会用到频域转换,原因是频率滤波后,大部分图像信息集中到原点附近和其他少数几个区域,大部分区域是不重要的、或者值为0的,这样就可以大大减小数据的存储尺寸;然而在实际的计算中,压缩数据一般要解压为原始数据才能执行相关的计算和显示操作,因此频域方法可以助力数据存储压缩,却无助于减小计算中的数据的大小。