快速高斯滤镜算法
高斯滤波是很多图像处理算法中最关键性的一个中间步骤,实现快速高斯滤波算法具有很重要的意义。
通过拜读前辈们关于高斯滤波快速算法的相关文献,实现了自己的快速高斯滤波算法,并用NEON指令加速了将近6倍。
1. 均值滤波逼近高斯滤波
这种算法优点是简单。一般可以通过3次均值滤波就可以逼近高斯滤波的效果。当然,如果需要的精度更高,则需要更多次的均值滤波。简单均值滤波需要根据高斯的delta参数确定均值滤波的长度,delta是连续的,而均值滤波的长度是整数,这样造成对不同的delta的逼近有一定的误差。均值滤波的O(1)时间复杂度的实现需要一个积分图去做,需要占用一个和原始图片相当的缓存。这样均值滤波逼近高斯滤波需要计算3次积分图,遍历3次积分图来计算均值。而且,这种算法没法采用CPU的SIMD指令加速。
对均值滤波逼近高斯滤波及其精度改进的算法可以参考下面的文献:
Peter Kovesi 2009, Arbitrary Gaussian Filtering with 25 Addtions and 5 Multiplications per Pixel
2. 扩展二项式滤波逼近高斯滤波
这一算法的参考文献为:
extended binomial filter for Fast gaussian Blur
这种算法的思路仍然是用均值逼近,只是每次均值滤波的长度不同,而且是一种加权的均值。但是在实现的时候没有用积分图,而是递归计算均值。参考文献里面提供了源代码,其源代码为photoshop的一种插件语言写的。应该是我太愚钝,没有彻底领悟算法细节,它的代码里面几个重要的初始参数不知道如何确定。
根据我的经验,上述算法在实际中并不比递归滤波实现的要快,因为它的代码里面在做竖直方向上递归计算均值滤波的时候是跨行访问图像数据的。这种算法也没法用CPU的SIMD指令加速。
3. IIR滤波逼近高斯滤波
这种算法的参考文献主要有:
Rachid Deriche - "Recursively implementing the Gaussian and its derivatives", 1993.
Lucas J. van Vliet, Ian T. Young and Piet W. Verbeek - "Recursive Gaussian derivative Filters", 1998
Dave Hale, "Recursive Gaussian Filters", CWP-546
这种算法是实现是级联了两个IIR滤波器,其中一个是非因果的IIR滤波过程。
另外,intel网站有一篇关于用SSE指令优化之后的IIR递归逼近高斯滤波的代码,不过代码写的太庞杂了,非专业人士可及也!
关于IIR滤波实现高斯滤波有很多的编程技巧,尤其是在用NEON指令加速递归IIR滤波的时候,具体细节不便阐述。
4. IIR递归高斯滤波的性能测试
4.1 与Photoshop cs5.0版本的对比
时间 | 处理器 | |
Photoshop CS5.0高斯滤镜 半径250 700W像素彩色照片 | 1.5秒 | intel I3 CPU主频2.3Ghz 2G内存 |
My 高斯滤镜 半径250 700W像素彩色照片 | 1秒 | intel I3 CPU主频2.3Ghz 2G内存 |
注:PS cs5的高斯对不同半径的高斯滤波做了不同的优化,它在半径很小的时候极快,不排除其做了多核优化,而IIR递归滤波算法对所以的半径计算时间完全一样。
4.2 在RVDS环境下的性能测试数据
指令数 | 周期数 | 处理器 | |
C 代码,1024x768 灰度图像 | 110M | 194M | ARM-cortex A8 |
NEON指令汇编代码,1024x768 灰度图像 | 34M | 35M | ARM-cortex A8 |
C 代码,1024x768 彩色图像 | 338M | 558M | ARM-cortex A8 |
NEON指令汇编代码,1024x768 彩色图像 | 84M | 85M | ARM-cortex A8 |
4.3 在IPod真实设备上的测试数据
时间 | 设备 | |
NEON指令汇编代码,720x576 灰度图像 | 25ms | IPod4 |
4.4 内存消耗
内存RAM消耗 | |
C代码 | 2 * MAX(width,height) |
NEON指令汇编代码 | 8 * MAX(width,height) |