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');


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?

  • 1
    $\begingroup$ @LaurentDuval Hi. Thanks for providing an answer. I will have to re-read your answers more carefully a little later. $\endgroup$ – nbro Jun 17 '19 at 20:38
  • $\begingroup$ Don't hesitate to ask for more details $\endgroup$ – 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.

| improve this answer | |
  • $\begingroup$ 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? $\endgroup$ – nbro Jun 3 '19 at 15:59
  • $\begingroup$ imfilter(I,[1,-1],'circ') is the same as imfilter(I,[1,-1],'circ'). $\endgroup$ – nbro Jun 4 '19 at 18:59
  • $\begingroup$ They are exactly the same commands $\endgroup$ – Laurent Duval Jun 4 '19 at 20:12
  • $\begingroup$ Lost a transpose there, sorry. I edited my reply to correct the mistake. $\endgroup$ – 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.

enter image description here

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.

enter image description here

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
| 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.