# Generate the Convolution Matrix of 2D Kernel for Convolution Shape of same

I want to find a convolution matrix for a certain 2D kernel $$H$$.
For example, for image Img of size $$m \times n$$ , I want (in MATALB):

T * Img = reshape(conv2(Img, H, 'same'), [], 1);


Where T is the convolution matrix and same means the Convolution Shape (Output Size) matched the input size.

Theoretically, H should be converted to a toeplitz matrix, I'm using the MATLAB function convmtx2():

T = convmtx2(H, m, n);


Yet T is of size $$(m+2) (n+2) \times (mn)$$ as MATLAB's convmtx2 generates a convolution matrix which matches Convolution Shape of full.

Is there a way to generate the Convolution Matrix which matches using conv2() with the same convolution shape parameter?

• Are you looking simply to get the same resultant T*Img or you would like to use T for a different purpose? Mar 28 '12 at 19:01
• I edited your code and maths so it looks more atractive. You can do this yourself on future questions. For Latex editing use . Jun 29 '12 at 13:18
• Related question - dsp.stackexchange.com/questions/17418.
– Royi
Jan 17 '19 at 8:58

I cannot test this on my computer because I do not have the convtmx2 function, here is what the MATLAB help says:

http://www.mathworks.com/help/toolbox/images/ref/convmtx2.html

T = convmtx2(H,m,n) returns the convolution matrix T for the matrix H. If X is an m-by-n matrix, then reshape(T*X(:),size(H)+[m n]-1) is the same as conv2(X,H).

This would get the same resulting convolution of conv2(X,H) but then you would still have to pull out the correct piece of the convolution.

• Welcome to DSP.SE, and this is a great answer! Mar 29 '12 at 2:37
• I think that sometimes one needs the actual matrix to analyze it (The adjoint operator, the inverse, etc...). Hence this method won't work (Unless you start removing rows form the matrix which will be slow as it is Sparse).
– Royi
Jan 17 '19 at 15:05

I wrote a function which solves this in my StackOverflow Q2080835 GitHub Repository (Have a look at CreateImageConvMtx()).
Actually the function can support any convolution shape you'd like - full, same and valid.

The code is as following:

function [ mK ] = CreateImageConvMtx( mH, numRows, numCols, convShape )

CONVOLUTION_SHAPE_FULL  = 1;
CONVOLUTION_SHAPE_SAME  = 2;
CONVOLUTION_SHAPE_VALID = 3;

switch(convShape)
case(CONVOLUTION_SHAPE_FULL)
% Code for the 'full' case
convShapeString = 'full';
case(CONVOLUTION_SHAPE_SAME)
% Code for the 'same' case
convShapeString = 'same';
case(CONVOLUTION_SHAPE_VALID)
% Code for the 'valid' case
convShapeString = 'valid';
end

mImpulse = zeros(numRows, numCols);

for ii = numel(mImpulse):-1:1
mImpulse(ii)    = 1; %<! Create impulse image corresponding to i-th output matrix column
mTmp            = sparse(conv2(mImpulse, mH, convShapeString)); %<! The impulse response
cColumn{ii}     = mTmp(:);
mImpulse(ii)    = 0;
end

mK = cell2mat(cColumn);

end


Enjoy...