最快的高斯模糊实现
如何实现最快的高斯模糊算法?
我将用Java实现它,因此排除了GPU解决方案。我的应用程序planetGenesis是跨平台的,所以我不需要JNI。
解决方案
我们可能希望框模糊,这要快得多。请参阅此链接,获取出色的教程以及一些复制和粘贴C代码的信息。
我会考虑为此使用CUDA或者其他一些GPU编程工具包,特别是如果我们想使用更大的内核。如果不这样做,总会在组装中手动调整循环。
数学笑话很可能知道这一点,但对于其他人来说。
由于高斯的数学性质很好,我们可以通过首先在图像的每一行上运行一维高斯模糊,然后在每一列上运行一维模糊,来快速对2D图像进行模糊。
- 步骤1:SIMD一维高斯模糊
- 步骤2:移调
- 步骤3:重复步骤1
最好在小块上完成,因为全图像转置比较慢,而小块转置可以使用一连串的PUNPCK(PUNPCKHBW,PUNPCKHDQ,PUNPCKHWD,PUNPCKLBW,PUNPCKLDQ,PUNPCKLWD)来完成。
我们应该使用一个事实,即高斯核是可分离的,即。 e。我们可以将2D卷积表示为两个1D卷积的组合。
如果滤波器很大,则使用空间域中的卷积等效于频率(傅里叶)域中的乘法这一事实也很有意义。这意味着我们可以对图像和滤镜进行傅立叶变换,将(复杂)结果相乘,然后进行傅立叶逆变换。 FFT(快速傅立叶变换)的复杂度为O(n log n),而卷积的复杂度为O(n ^ 2)。同样,如果我们需要使用同一滤镜模糊许多图像,则只需对滤镜进行一次FFT。
如果我们决定继续使用FFT,则FFTW库是一个不错的选择。
- 我找到了Quasimondo:孵化器:处理:快速高斯模糊。此方法包含许多近似值,例如使用整数和查找表,而不是浮点数和浮点除法。我不知道现代Java代码中有多少加速。
- 矩形上的快速阴影具有使用B样条的近似算法。
- C#中的快速高斯模糊算法声称具有一些很酷的优化。
- 而且,David Everly的Fast Gaussian Blur(PDF)具有一种用于Gaussian模糊处理的快速方法。
我将尝试各种方法,对其进行基准测试,然后将结果发布在此处。
出于我的目的,我从Internet复制并实现了基本(独立处理X-Y轴)方法和David Everly的Fast Gaussian Blur方法。它们的参数不同,所以我无法直接比较它们。但是,对于较大的模糊半径,后者经过的迭代次数要少得多。同样,后者是一种近似算法。
对于较大的模糊半径,请尝试应用三次框模糊。这将很好地近似高斯模糊,并且比真正的高斯模糊快得多。
在1D中:
反复使用几乎所有内核进行模糊处理都倾向于使用高斯内核。这就是高斯分布的奇妙之处,也是统计学家喜欢它的原因。因此,请选择易于模糊的内容并将其应用多次。
例如,使用盒形内核很容易模糊。首先计算一个累计和:
y(i) = y(i-1) + x(i)
然后:
blurred(i) = y(i+radius) - y(i-radius)
重复几次。
或者我们可能会使用各种IIR滤波器来回移动几次,这些速度同样快。
在2D或者更高版本中:
正如DarenW所说,每个维度都一个接一个地模糊。
我在研究过程中为这个问题而苦苦挣扎,并尝试了一种有趣的快速高斯模糊方法。首先,如前所述,最好将模糊分为两个一维模糊,但是根据实际用于像素值计算的硬件,我们实际上可以预先计算所有可能的值并将它们存储在查找表中。
换句话说,预先计算"高斯系数" *"输入像素值"的每个组合。当然,我们需要谨慎考虑系数,但是我只是想添加此解决方案。如果我们具有IEEE订阅,则可以使用"查找表"进行实时特征提取,以获取快速图像模糊中的更多内容。
最终,我最终还是使用了CUDA :)