OpenCV:filter2D函数的计算效率

OpenCV: Computational efficiency of filter2D function

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

filter2D 会比 post 中提供的代码更快吗?如果是,是什么让它更快?

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

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

  1. 可分离卷积。 对某些类型的内核利用 "associative property of convolution"。对于 M-by-N 图像和 P-by-Q 内核,天真的方法是 M*N*P*Q。如果内核是可分离的,您可以在 M*N(P+Q) 中进行。那是巨大的!您会注意到 OpenCV 的 filter2d 源在可能的情况下利用了这一点。阅读更多相关信息 here.

  2. 卷积定理。这种优化更好,但有点复杂。基本上:空间域中的卷积等效于频域中的逐点乘法。这意味着如果您将图像和内核通过 FFT,您的卷积可以从二次(天真的)时间复杂度为 O(n log n)!查看 Convolution theorem on Wikipedia

Filter2d 在您的过滤器尺寸较小时非常有效,并且比您提到的 post 更快。但是,当内核变大时,运行时间会急剧增加。

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

递归实现的核心思想是2D卷积可以分离成多个1D卷积,1D卷积可以写成递归。 google 关于递归高斯滤波器或递归卷积。

此外,您可以分解内核并使用多个积分图像实现卷积。仅google关于核积分图像或余弦积分图像。

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

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

如果你首先关心实现效率,那你最好学习一下,自己写一个filter2d。如果没有,就用opencv的filter2d,记住避免大内核。