# Replicate MATLAB's conv2() in Frequency Domain

When conv2d is on same mode, the image needs no padding, because the result is the same size as the image.

When conv2d is on full mode, the result is (image_width + kernel_width -1) * (image_height + kernel_height -1).

Then how do I pad the image?

• Does it help? stackoverflow.com/questions/12253984/… Apr 29, 2021 at 3:24
• @ZRHan Very helpful! Thank you so much! Should I delete my question because of duplication? Apr 29, 2021 at 7:06
• I think closing it is OK. Apr 29, 2021 at 8:16
• @MageFront, I wrote a full answer. Don't delete. Please mark my answer.
– Royi
Apr 29, 2021 at 8:37
• – Royi
Apr 29, 2021 at 9:01

I created a MATLAB function which is basically conv2() applied in Frequency Domain:

function [ mO ] = ImageConvFrequencyDomain( mI, mH, convShape )
% ----------------------------------------------------------------------------------------------- %
% [ mO ] = ImageConvFrequencyDomain( mI, mH, convShape )
% Applies Image Convolution in the Frequency Domain.
% Input:
%   - mI                -   Input Image.
%                           Structure: Matrix.
%                           Type: 'Single' / 'Double' (Single Channel).
%                           Range: (-inf, inf).
%   - mH                -   Filtering Kernel.
%                           Structure: Matrix.
%                           Type: 'Single' / 'Double'.
%                           Range: (-inf, inf).
%   - convShape         -   Convolution Shape.
%                           Sets the convolution shape.
%                           Structure: Scalar.
%                           Type: 'Single' / 'Double'.
%                           Range: {1, 2, 3}.
% Output:
%   - mI                -   Output Image.
%                           Structure: Matrix (Single Channel).
%                           Type: 'Single' / 'Double'.
%                           Range: (-inf, inf).
% References:
%   1.  MATLAB's 'conv2()' - https://www.mathworks.com/help/matlab/ref/conv2.html.
% Remarks:
%   1.  A
% TODO:
%   1.
%   Release Notes:
%   -   1.0.000     29/04/2021  Royi Avital     RoyiAvital@yahoo.com
%       *   First release version.
% ----------------------------------------------------------------------------------------------- %

CONV_SHAPE_FULL     = 1;
CONV_SHAPE_SAME     = 2;
CONV_SHAPE_VALID    = 3;

numRows     = size(mI, 1);
numCols     = size(mI, 2);

numRowsKernel = size(mH, 1);
numColsKernel = size(mH, 2);

switch(convShape)
case(CONV_SHAPE_FULL)
numRowsFft  = numRows + numRowsKernel - 1;
numColsFft  = numCols + numColsKernel - 1;
firstRowIdx = 1;
firstColIdx = 1;
lastRowIdx  = numRowsFft;
lastColdIdx = numColsFft;
case(CONV_SHAPE_SAME)
numRowsFft  = numRows + numRowsKernel;
numColsFft  = numCols + numColsKernel;
firstRowIdx = ceil((numRowsKernel + 1) / 2);
firstColIdx = ceil((numColsKernel + 1) / 2);
lastRowIdx  = firstRowIdx + numRows - 1;
lastColdIdx = firstColIdx + numCols - 1;
case(CONV_SHAPE_VALID)
numRowsFft = numRows;
numColsFft = numCols;
firstRowIdx = numRowsKernel;
firstColIdx = numColsKernel;
% The Kernel when transformed is shifted (Namely its (0, 0) is top
% left not middle).
lastRowIdx  = numRowsFft;
lastColdIdx = numColsFft;
end

mO = ifft2(fft2(mI, numRowsFft, numColsFft) .* fft2(mH, numRowsFft, numColsFft), 'symmetric');
mO = mO(firstRowIdx:lastRowIdx, firstColIdx:lastColdIdx);

end



It is fully compatible and validated.
The full code is available on my StackExchange Signal Processing Q74803 GitHub Repository (Look at the SignalProcessing\Q74803 folder).