1
$\begingroup$

A lot of people use imfilter to achieve a 2-D convolution between an image and a filter, but the majority of people use conv2 instead of imfilter because it is faster than imfilter by at least 20%.

Examples:

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

Could someone explain to me in detail why conv2 is faster than imfilter.

$\endgroup$
4
$\begingroup$

First, I think conv2 and imfilter will give you the same result if you change the filter option of imfilter to conv instead of corr. imfilter uses correlation to filter images by default that starts from one side of the image, whereas covolution starts from the other, so there may be some small differences in the filter output.

Secondly, my test shows imfilter on 2D image is faster if the filter size if the same as images.

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

Both imfilter and conv2 are hardware optimized and multi-threaded. For floating point inputs, the performance of them are supposed to be roughly the same. But in most cases in image processing, the filter kernel is linearly separable, imfilter does separation of the kernel into row and column vectors. As a result, they are much faster. Yet if the filter kernel is (1) not linearly separable, or (2) a small kernel such as a 5*5 filter kernel. conv2 wins in the processing time. I guess the reason is some time is spent on checking the separability of the kernel in imfilter. I am not sure whether there are other different mechanisms that leads to the processing time difference between the two.

Finally, if the filter size is the same as image. fft is always the best one (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

EDIT

@geometrikal's detailed analysis: The reason fft is faster than imfilter with same size images is that imfilter pads the inputs (even with 'same'). For small filter kernels, not much padding is needed for imfilter, whereas to use the fft the kernel will have to be padded to the size of the image. In these cases imfilter is faster.

$\endgroup$
  • $\begingroup$ Firstly, thank you very much for your answer!. By using other than floating points like as grayscale images, your explanation remains the same ? In other words, instead of data=rand(200), the data can be a grayscale image $\endgroup$ – Christina Jan 1 '14 at 22:54
  • 1
    $\begingroup$ For integer input images (0-255 for example), imfilter has integer optimized code paths, so it is expected at least not much slower than conv2 I think. Yet fft2 is always the fastest $\endgroup$ – lennon310 Jan 1 '14 at 23:00
  • $\begingroup$ I appreciate very much your opinion. Thank you again Dear. $\endgroup$ – Christina Jan 1 '14 at 23:09
  • 1
    $\begingroup$ The reason fft is faster than imfilter with same size images is that imfilter pads the inputs (even with 'same'). For small filter kernels, not much padding is needed for imfilter, whereas to use the fft the kernel will have to be padded to the size of the image. In these cases imfilter is faster. $\endgroup$ – geometrikal Jan 2 '14 at 6:25
  • $\begingroup$ @geometrikal thank you for your response :) it is interested :) $\endgroup$ – Christina Jan 2 '14 at 10:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.