为什么与 MATLAB 的 imgaussfilt 相比,带有 skimage 和 scipy 的 2D 高斯滤波之间的速度差异如此之大?



我正在寻求将工作流程从MATLAB迁移到Python。我将对大量的大图像进行过滤,并立即遇到性能障碍。在MATLAB R2022a中使用10 sigma高斯滤波器滤波11587 by 13744需要不到两秒钟:

tic, imgf=imgaussfilt(im,10); toc
Elapsed time is 1.792801 seconds.

我用scipy1.8.0和skimage0.19.1尝试了同样的事情,两者都慢得多:

%timeit scipy.ndimage.gaussian_filter(im, 10, truncate=2)
4.89 s ± 15.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

慢2.7倍。

%timeit skimage.filters.gaussian(im, sigma=10, preserve_range=True, truncate=2)
5.99 s ± 14.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

慢了3.4倍。

请注意,truncate设置为2,我理解与MATLAB正在做的相匹配。我已经验证了输出的图像看起来是一样的,所以没有什么基本的错误。

在Python中是否有专门加速此操作(以及类似的图像处理任务)的解决方案?有些库通常被认为比其他库更快吗?例如,在上面,我已经看到scipy更快。

编辑:

  • opencv比上述两个更快,但仍然比MATLAB慢1.4倍左右。然而,这正在进入一个有用的领域。openv是多线程的,这似乎解释了差异。
  • dip(见下文)比MATLAB更快。dip.Gauss(img,10,truncation=2)在一秒钟内执行。
  • 更好的是,我发现我的图像不必是16位,opencv能够在600毫秒内过滤我的8位图像!奇怪的是,MATLAB需要13秒来过滤这样的图像。所以我认为我们有赢家了。

MATLAB的imgaussfilt根据数据的维数,选择是采用空间域处理还是傅里叶域处理。

在某些情况下,它的选择可能会创建优化的计算,这解释了您所看到的收益。

如果你在追求最快的空间滤波使用高斯滤波器,你可能应该使用英特尔IPP。

总之:我为我的用例找到的最佳解决方案是从16位转换为8位并使用opencv。如果我不想移动到16位,DIPlib会更快。与MATLAB的函数相比,某些Python包的性能较慢的主要原因似乎是由于它们不是多线程的。

最新更新