如果我想在OpenCV中使用内核对图像进行卷积,我可以使用filter2D
函数。另一个选择是使用for循环创建我自己的过滤器,如this post中所示。
filter2D会比帖子中提供的代码更快吗?如果是的话,是什么让它更快?
我试着看code for filter2d,但无法理解。我是openCV的新手,对此方面的任何帮助表示赞赏。
答案 0 :(得分:6)
事实上,大多数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
答案 1 :(得分:3)
当您的过滤器尺寸较小时,Filter2d非常有效,并且比您引用的帖子更快。但是,当内核变大时,运行时会急剧增加。
事实上,有许多实现比OpenCV快得多,包括那些基于递归和整数图像的实现。
递归实现的关键思想是2D卷积可以分成几个1D卷积,1D卷积可以写成递归。只是谷歌关于递归guassian过滤器或递归卷积。
此外,您可以分解内核并使用几个积分图像实现卷积。只是谷歌关于内核积分图像或余弦积分图像。
无论哪种方式,运行时都不会随内核大小而增加。因此,当内核很大时,这些实现比OpenCV的filter2d更有效。
理解递归实现或积分图像实现需要一些关于信号处理的数学背景。
如果实施效率是您首先考虑的问题,那么您最好先学习它们并自己编写一个filter2d。如果没有,只需使用opencv的filter2d,记住避免使用大内核。