As a newbie, I wrote a custom function in octave to perform a 2D image convolution using separable kernels. The results of this custom function were compared with conv2() and they were consistent. But that was where the joy ended.

conv2() works at the speed of light while my custom function is slower than a steam locomotive.

How can I speed up the loops below? As you can see, the number of MACs per pixel is 6 compared to 9 that would have been the case in 2D convolution. The function takes as inputs a row vector(3x1) and a column vector(1x3).

function OutputImage = Convolve3X3(InputImage, RowCount, ColCount, Kernel_x, Kernel_y)

% Create a padded image
PaddedImage = uint8(zeros(RowCount + 2, ColCount + 2));

% Create a staging area
StagingImage = uint8(zeros(RowCount + 2, ColCount + 2));

% Create a Row Vector
RowVector = uint8(zeros(1,3));

% Create a Col Vector
ColVector = uint8(zeros(3,1));

% Copy the input image into the padded image
PaddedImage(2:RowCount + 1, 2:ColCount + 1) = InputImage;

% 1D convolution of necessary rows with Kernel_x
for i = 2: RowCount + 1
  for j = 1:ColCount
   RowVector = PaddedImage(i,j:j+2) .* Kernel_x;
   StagingImage(i,j) = RowVector(1) + RowVector(2) + RowVector(3);

% 1D convolution of necessary columns with Kernel_y
for i = 1: RowCount 
  for j = 1:ColCount
   ColVector = StagingImage(i:i+2,j) .* Kernel_y;  
   OutputImage(i,j)  = ColVector(1) + ColVector(2) + ColVector(3);


How is conv2() so radically fast?


Because loops in MATLAB/Octave are slow (mostly because they are interpreted languages not compiled) and such operations are typically implemented in C/C++ for performance reasons. You could even further speed these up by reverting to better C/C++ implementations and writing your mex wrappers.

| improve this answer | |

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.