OpenCV:filter2D函数的计算效率

Posted

技术标签:

【中文标题】OpenCV:filter2D函数的计算效率【英文标题】:OpenCV: Computational efficiency of filter2D function 【发布时间】:2015-07-10 08:39:37 【问题描述】:

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

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

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

【问题讨论】:

尝试分析它!通常 OpenCV 代码比简单的实现要快得多,因为很多很酷的程序员对其进行了很好的优化,在某些情况下也使用硬件加速。 很可能会更快。编码卷积/矩阵乘法有很多不直观的方法,而不是加快计算速度,openCV 使用它们。数学家在这些事情上工作了很多。检查示例矩阵乘法算法:en.wikipedia.org/wiki/… 我也认为它应该更快,这就是为什么我尝试尽可能使用过滤器执行任务。 【参考方案1】:

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

    可分离卷积。利用特定类型内核的“卷积的关联属性”。对于M-by-N 图像和P-by-Q 内核,天真的方法是M*N*P*Q。如果内核是可分离的,您可以在M*N(P+Q) 中进行。那是巨大的!您会注意到 OpenCV 的 filter2d 源代码尽可能利用了这一点。阅读更多关于它的信息here。

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

【讨论】:

感谢@Adam 的回答。【参考方案2】:

当您的过滤器尺寸较小时,Filter2d 是有效的,并且比您引用的帖子更快。但是,当内核变大时,运行时间会急剧增加。

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

递归实现的关键思想是2D卷积可以分离成几个1D卷积,1D卷积可以写成递归。只是谷歌关于递归高斯滤波器或递归卷积。

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

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

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

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

【讨论】:

感谢您的回复。我在使用 Viola Jones 人脸检测代码时读过积分图像,它应该比卷积更快。我会阅读更多关于它的信息,看看我是否可以更频繁地使用它。

以上是关于OpenCV:filter2D函数的计算效率的主要内容,如果未能解决你的问题,请参考以下文章

opencv4opencv视频教程 C++(opencv教程)3矩阵的掩膜操作(filter2D)

手撕OpenCV源码之filter2D

卷积处理过程模拟:用Python实现OpenCV函数filter2D等效的卷积功能

Python-OpenCV中的filter2D()函数

OpenCV filter2D和sepFilter2D

python使用openCV图像加载(转化为灰度图像)使用filter2D函数对图像进行锐化(Sharpen Images)