MATLAB 的 `conv2()` 与 `imfilter()` 的性能

信息处理 图像处理 matlab 过滤器 离散信号 卷积
2022-02-14 16:46:46

很多人使用imfilter来实现图像和过滤器之间的二维卷积,但大多数人使用conv2而不是imfilter因为它比imfilter至少快 20%。

例子:

filtered_image_with_imfilter = imfilter(image,filter,'symmetric','same','corr');
filtered_image_with_conv2 = conv2(image,filter,'same');

有人可以详细解释一下为什么conv2imfilter.

2个回答

首先,如果您将过滤器选项更改为to而不是,我认为conv2并且imfilter会给您相同的结果默认情况下,使用相关性来过滤从图像的一侧开始的图像,而卷积是从另一侧开始的,因此过滤器输出可能会有一些小的差异。imfilterconvcorrimfilter

其次,imfilter如果过滤器大小与图像相同,我在 2D 图像上的测试会更快。

clc
data = (rand(200));
kernel = ones(200)/4e4;
tic
blurredData = conv2(data, kernel,'same');
conv2t=toc
tic
blurredData = imfilter(data, kernel,'same','conv');
imfiltime=toc

>> conv2t =

       2.7425


  imfiltime =

       0.1552

imfilter 和都是conv2硬件优化和多线程的。对于浮点输入,它们的性能应该大致相同。但在图像处理中的大多数情况下,滤波器内核是线性可分的,imfilter将内核分离为行向量和列向量。结果,它们的速度要快得多。然而,如果滤波器内核 (1) 不是线性可分的,或者 (2) 是一个小内核,例如 5*5 滤波器内核。conv2在处理时间上获胜。我猜原因是花了一些时间检查内核在imfilter. 我不确定是否还有其他不同的机制导致两者之间的处理时间差异。

最后,如果过滤器大小与图像相同。fft永远是最好的(O(nlogn)):

clc
data = (rand(200));
kernel = ones(200)/4e4;
tic
blurredData = conv2(data, kernel,'same');
conv2t=toc
tic
blurredData = imfilter(data, kernel,'same','conv');
imfiltime=toc
tic
D=fft2(data);
K=fft2(kernel);
blurdata=ifft2(D.*K);
fftime=toc


>>conv2t =

          2.7429


  imfiltime =

          0.1327


  fftime =

          0.0164

编辑

@geometrikal 的详细分析:fft 比具有相同大小图像的 imfilter 更快的原因是 imfilter 填充了输入(即使使用“相同”)。对于小的过滤器内核,imfilter 不需要太多的填充,而要使用 fft,内核必须填充到图像的大小。在这些情况下,imfilter 更快。

对于一维情况,我认为 conv() 是在直接域中实现的,而 xcorr 是在频域中实现的。

这表明对于小内核,conv 会更快,而当输入大小相等时,xcorr 会更快。

我不知道这是否仍然是这种情况,以及它是否扩展到二维情况。

通过将输入从双精度转换为单精度(例如 fft),允许本机单精度的操作可以快 2 倍。在某些情况下,即使函数使用 fft 进行繁重的工作,它也不允许端到端的单精度。

通过考虑 Matlab 的以列为主的性质,有时可以通过在内存中仔细布局操作来实现大的加速(4 倍或更多),这样就不需要大的跳转和分散/聚集。