# What do the 1D filters represent when using imfilter?

I am reading the source code of an algorithm that is used to process an image. While reading this source code (and others), I've found lines of code of the form

imfilter(image, [0.25 0 -0.25]', 'circular');


or

imfilter(image, [1 0 -1], 'circular');


I don't get what these kernels [0.25 0 -0.25]' (the transpose) or [1 0 -1] represent. Shouldn't kernels be 2D if the input is an image? What exactly do these specific kernels do to the image? I have seen several examples of imfilter being applied to an image with kernels of this form and I don't understand what the results of these operations should be (when I read the source code). Can someone provide some intuition?

• @LaurentDuval Hi. Thanks for providing an answer. I will have to re-read your answers more carefully a little later. – nbro Jun 17 '19 at 20:38
• Don't hesitate to ask for more details – Laurent Duval Jul 2 '19 at 19:33

If I'm not mistaken, a column vector will filter the image across its columns, treating each row independently of the others. Likewise, a row vector will filter across rows, treating all columns the same.

edit: Regarding an example - consider the simple image [1,1,1;0,0,0;-1,-1,-1]. It's constant along its rows (i.e., all the columns are the same) and a gradient along its columns. Let's filter it with a differentiating filter kernel [1,-1] along rows or columns. If we do imfilter(I,[1,-1],'circ') we obtain the zero image: since the image was constant along rows, filtering each row with a differentiating kernel gives the zero image. Oh the other hand, for imfilter(I,[1,-1]','circ') we obtain [1,1,1;1,1,1;-2,-2,-2]: each column gets differentiated independently and since all columns are the same, the resulting image is constant along rows.

As for the 0.25: this is merely a scaling of the whole image. You might as well filter with 1 as a filter weight and divide the result by 4, the effect is the same.

• I think a simple example would help to clarify it. Furthermore, what does it mean to use $1$ as opposed e.g. to $0.25$ in the filters? – nbro Jun 3 '19 at 15:59
• imfilter(I,[1,-1],'circ') is the same as imfilter(I,[1,-1],'circ'). – nbro Jun 4 '19 at 18:59
• They are exactly the same commands – Laurent Duval Jun 4 '19 at 20:12
• Lost a transpose there, sorry. I edited my reply to correct the mistake. – Florian Jun 5 '19 at 8:16

First, the circular option relates to the treatment of the borders of the image. Then, standard image kernels can be any $$[r,c]$$ matrix. If either $$r$$ or $$c$$ is equal to $$1$$, then this is a very flat $$2D$$ filter, that acts only across one direction: across lines if horizontal, across columns if vertical (with the transpose).

Filtering is a linear operation: if $$f$$ is a filter, and $$a$$ a scalar, $$I*(a.f) = a.I*(f)$$. So, very often in image processing, filters can be used with different normalization factors, as long as normalization is not important for the task. For instance, to compute a maximum, a zerocrossing, normalization does not really matters as long as computations are done with sufficient precision. Let us look at the shape of the filters. You can have a bigger picture by looking at its affect on simple images. For instance, an impulse image. As you see $$[0.25 0 -0.25]$$ and $$[0.25 0 -0.25]'$$ act similarly, horizontally and vertically. $$[1 0 -1]$$ seems to act as $$[0.25 0 -0.25]$$, but with a four factor on the amplitude (colorbar). They all are versions of a 3-point centered discrete derivative. If you look for location of sharp variations, or their relative magnitude, it seems ok. Since such filters estimate the slope, I would have used $$[1 0 -1]/2$$ instead.

But the problem appears when you work with limited precision. For instance on a uint8 image, outputs can be saturated, cropped and rounded. You can see that when uncommenting the line

%imageImpulse = uint8(imageImpulse);


in the code below. %SeDsp58669
nRow = 32 ; nCol = 32;
locImpulse = floor([nRow,nCol])/2;
imageImpulse = zeros(nRow,nCol);
imageImpulse(locImpulse(1),locImpulse(2)) = 1;
%imageImpulse = uint8(imageImpulse);
filterCoefficient1 = [0.25 0 -0.25];
filterCoefficient2 = [0.25 0 -0.25]';
filterCoefficient3 = [1 0 -1];
imageImpulseFilt1 = imfilter(imageImpulse, filterCoefficient1, 'circular');
imageImpulseFilt2 = imfilter(imageImpulse, filterCoefficient2, 'circular');
imageImpulseFilt3 = imfilter(imageImpulse, filterCoefficient3, 'circular');
colormap gray
subplot(2,2,1)
imagesc(imageImpulse);colorbar
xlabel('Impulse')
subplot(2,2,2)
imagesc(imageImpulseFilt1);colorbar
xlabel(num2str(filterCoefficient1))
subplot(2,2,3)
imagesc(imageImpulseFilt2);colorbar
xlabel(num2str(filterCoefficient2))
subplot(2,2,4)
imagesc(imageImpulseFilt3);colorbar
xlabel(num2str(filterCoefficient3))