OpenCV: filter2D函数的计算效率



如果我想在OpenCV中使用内核对图像进行卷积,我可以使用filter2D函数。另一种选择是像这篇文章中那样使用for循环创建我自己的过滤器。

filter2D会比文章中的代码更快吗?如果是,是什么让它更快?

我试着看filter2d的代码,但无法理解。我是openCV的新手,在这方面的任何帮助都是非常感谢的。

事实上,大多数OpenCV都比朴素的方法快得多!对于卷积,它们通常使用以下两种基本优化之一:

  1. 分离卷积。对某些类型的内核利用了"卷积的关联属性"。对于M-by-N图像和P-by-Q核,天真的方法是M*N*P*Q。如果内核是可分离的,你可以在M*N(P+Q)中完成。这是巨大的!你会注意到OpenCV的filter2d源代码在可能的情况下利用了这一点。

  2. 卷积定理。这种优化甚至更好,但它有点复杂。基本上:空间域中的卷积相当于频域中的逐点乘法。这意味着如果你把你的图像和内核通过FFT,你的卷积可以从二次(朴素)时间复杂度到O(n log n)!查看Wikipedia上的卷积定理

Filter2d是有效的,当你的过滤器大小是小的,并且比你提到的帖子更快。但是,当内核变大时,运行时会急剧增加。

事实上,有许多实现比OpenCV快得多,包括那些基于递归和积分图像的实现。

递归实现的关键思想是二维卷积可以分离成几个一维卷积,一维卷积可以写成递归。谷歌一下递归高斯滤波器或者递归卷积就知道了。

同样,你可以分解你的核并使用几个积分图像实现卷积。谷歌一下核积分图像或者余弦积分图像。

无论哪种方式,运行时都不会随着内核大小的增加而增加。因此,当你的内核很大时,这些实现比OpenCV的filter2d要高效得多。

理解递归实现或积分图像实现需要一些信号处理的数学背景。

如果实现的效率是你最关心的,你最好学习它们并自己编写一个过滤器。如果没有,就使用opencv的filter2d,记住要避免大内核。

相关内容

  • 没有找到相关文章

最新更新