Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - 2D Convolution

Tags:

I'm trying to do in C language a convolution of matrices.

I've tried something but cannot do it properly.

N[WIDTH1][WIDTH2] is the input matrix, M[MASK_WIDTH1][MASK_WIDTH2] is the kernel matrix, P[][] the output matrix.

First attempt:

void convolution_2D(int N[][WIDTH2], int M[][MASK_WIDTH2], int P[][WIDTH2]) {

// find center position of kernel (half of kernel size)
int kCenterX = MASK_WIDTH2 / 2;
int kCenterY = MASK_WIDTH1 / 2;

for (int i = 0; i < WIDTH1; ++i)              // rows
{
    for (int j = 0; j < WIDTH2; ++j)          // columns
    {
        for (int m = 0; m < MASK_WIDTH1; ++m)     // kernel rows
        {
            int mm = MASK_WIDTH1 - 1 - m;      // row index

            for (int n = 0; n < MASK_WIDTH2; ++n) // kernel columns
            {
                int nn = MASK_WIDTH2 - 1 - n;  // column index

                // index of input signal, used for checking boundary
                int ii = i + (m - kCenterY);
                int jj = j + (n - kCenterX);

                // ignore input samples which are out of bound
                if (ii >= 0 && ii < WIDTH1 && jj >= 0 && jj < WIDTH2)
                    P[i][j] += N[ii][jj] * M[mm][nn];
            }
        }
    }
}

The problem is that the boundary values are wrong, because I pick the wrong values of the M matrix. For example, for P[0][0] the result should be, for N and P 5x5 and M 3x3:

P[0][0] = N[0][0]*M[1][1] + N[0][1]*M[1][2] + N[1][0]*M[2][1] + N[1][1]*M[2][2];

The values of the kernel that I need are the lower right part; instead, that code picks the upper left part and I can't write the code to check the right values.

like image 920
Pleasant94 Avatar asked Jan 03 '17 20:01

Pleasant94


1 Answers

The values of the kernel that I need are the lower right part; instead, that code picks the upper left part and I can't write the code to check the right values.

This is because you are flipping the mask indices when you compute mm and nn. Simply remove those lines and use m and n to index the mask:

if (ii >= 0 && ii < WIDTH1 && jj >= 0 && jj < WIDTH2)
    P[i][j] += N[ii][jj] * M[m][n];
like image 115
samgak Avatar answered Sep 23 '22 10:09

samgak