Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image convolution with even-sized kernel

I want to perform a simple 2D image convolution but my kernel is even-sized. Which indices I should pick for my kernel center? I tried googling for an answer and looking existing codes. People usually center their kernel so there would be one sample more before the new 0. So, if we have a 4x4 kernel the centered indices should be -2 -1 0 +1. Is that correct? And if it is, why is that so? Can someone explain why -2 -1 0 +1 is correct while -1 0 +1 +2 is not? Keep in mind that I want to perform the convolution without using FFT.

like image 582
AstrOne Avatar asked Jun 11 '13 03:06

AstrOne


People also ask

How does kernel size affect convolution?

A common choice is to keep the kernel size at 3x3 or 5x5. The first convolutional layer is often kept larger. Its size is less important as there is only one first layer, and it has fewer input channels: 3, 1 by color.

Can a kernel be even?

Other than that, Even sized kernels can also be used but those Images cannot be padded means No Padding (Valid Padding) is necessary for it. Another reason for using Odd sized kernel is that all the previous layer pixels would be Symmetric around the Output pixel.

Does kernel size have to be odd?

Why kernel size is odd ? For an odd-sized filter, all the previous layer pixels would be symmetrical around the output pixel. Without this symmetry, we will have to account for distortions across the layers.

What is kernel in image convolution?

In image processing, a kernel, convolution matrix, or mask is a small matrix used for blurring, sharpening, embossing, edge detection, and more.


2 Answers

If I understand your question correctly, then for even sized kernels you are correct that it is the convention to centre the kernel so that there is one more sample before the new zero.

So, for a kernel of width 4, the centred indices will be -2 -1 0 +1 as you say above.

However, this really is just a convention - an asymmetric convolution is very rarely used anyway and the exact nature of the asymmetry (to the left/right etc.) has no relation to the "correct" result. I would imagine that the reason that most implementations behave this way is so that they can give comparable results given the same inputs.

When performing the convolution in the frequency domain, the kernel is padded to match the image size anyway, and you've already stated that you are performing the convolution in the spatial domain.

I'm much more intrigued as to why you need to use an even sized kernel in the first place.

like image 78
Roger Rowland Avatar answered Oct 23 '22 19:10

Roger Rowland


The correct answer is to return the results pixel in the upper left corner, regardless whether your matrix is evenly sized or not. Then you can simply perform the operation in a simple scanline, and they require no memory.

private static void applyBlur(int[] pixels, int stride) {
    int v0, v1, v2, r, g, b;
    int pos;
    pos = 0;
    try {
        while (true) {
            v0 = pixels[pos];
            v1 = pixels[pos+1];
            v2 = pixels[pos+2];

            r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
            g = ((v0 >> 8 ) & 0xFF) + ((v1 >>  8) & 0xFF) + ((v2 >>  8) & 0xFF);
            b = ((v0      ) & 0xFF) + ((v1      ) & 0xFF) + ((v2      ) & 0xFF);
            r/=3;
            g/=3;
            b/=3;
            pixels[pos++] = r << 16 | g << 8 | b;
        }
    }
    catch (ArrayIndexOutOfBoundsException e) { }
    pos = 0;
    try {
    while (true) {
            v0 = pixels[pos];
            v1 = pixels[pos+stride];
            v2 = pixels[pos+stride+stride];

            r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
            g = ((v0 >> 8 ) & 0xFF) + ((v1 >>  8) & 0xFF) + ((v2 >>  8) & 0xFF);
            b = ((v0      ) & 0xFF) + ((v1      ) & 0xFF) + ((v2      ) & 0xFF);
            r/=3;
            g/=3;
            b/=3;
            pixels[pos++] = r << 16 | g << 8 | b;
        }
    }
    catch (ArrayIndexOutOfBoundsException e) { }
}
like image 35
Tatarize Avatar answered Oct 23 '22 19:10

Tatarize