Ruc*_*hir 3 c++ opencv image-processing
如果我想在OpenCV中使用内核对图像进行卷积,我可以使用该filter2D函数.另一种选择是使用for循环创建我自己的过滤器,如本文所述.
filter2D会比帖子中提供的代码更快吗?如果是的话,是什么让它更快?
事实上,大多数OpenCV比天真的方法快得多!对于卷积,他们经常使用以下两种基本优化中的一种:
可分离的卷积. 对某些类型的内核利用"卷积的关联属性".对于M-by-N图像和P-by-Q内核,天真的方法是M*N*P*Q.如果内核是可分的,你可以进行M*N(P+Q).那太大了!您会注意到OpenCV的filter2d源尽可能利用了这一点.在这里阅读更多相关信息.
该卷积定理.这种优化甚至更好,但它有点复杂.基本上:空间域中的卷积等效于频域中的逐点乘法. 这意味着如果您将图像和内核通过FFT,您的卷积可以从二次(幼稚)时间复杂度变为O(n log n)!查看维基百科上的卷积定理
当您的过滤器尺寸较小时,Filter2d 非常高效,并且比您提到的帖子更快。然而,当内核变大时,运行时间急剧增加。
事实上,有很多实现比 OpenCV 快得多,包括基于递归和积分图像的实现。
递归实现的关键思想是2D卷积可以分成多个1D卷积,并且1D卷积可以写成递归。只需谷歌一下递归高斯滤波器或递归卷积即可。
此外,您可以分解内核并使用多个积分图像来实现卷积。只需谷歌一下内核积分图像或余弦积分图像即可。
无论哪种方式,运行时间都不会随着内核大小的增加而增加。因此,当内核很大时,这些实现比 OpenCV 的 filter2d 更高效。
了解递归实现或积分图像实现需要一些信号处理的数学背景。
如果实现的效率是你首先关心的,你最好学习它们并自己编写一个filter2d。如果没有,就使用opencv的filter2d,记住避免使用大内核。