C# Convolution filter for any size matrix (1x1, 3x3, 5x5, …) not fully applied

前端 未结 1 1311
北海茫月
北海茫月 2021-01-22 02:39

I\'m making a convolution filter for my project and I managed to make it for any size of matrix but as it gets bigger I noticed that not all bits are changed. Here are the pictu

相关标签:
1条回答
  • 2021-01-22 03:23

    The problem is that your code explicitly stops short of the edges. The calculation for the limits for your outer loops (nWidth and nHeight) shouldn't involve the size of the matrix, they should be equal to the size of your bitmap.

    When you do this, if you imagine what happens when you lay the center point of your matrix over each pixel in this case (because you need to read from all sizes of the pixel) the matrix will partially be outside of the image near the edges.

    There are a few approaches as to what to do near the edges, but a reasonable one is to clamp the coordinates to the edges. I.e. when you would end up reading a pixel from outside the bitmap, just get the nearest pixel from the edge (size or corner).

    I also don't understand why you need five loops - you seem to be looping through the height of the matrix twice. That doesn't look right. All in all the general structure should be something like this:

    for (int y = 0; y < bitmap.Height; y++) {
      for (int x = 0; x < bitmap.Width; x++) {
        int sum = 0;
    
        for (int matrixY = -matrix.Height/2; matrixY < matrix.Height/2; matrixY++)
          for (int matrixX = -matrix.Width/2; matrixX < matrix.Width/2; matrixX++) {
            // these coordinates will be outside the bitmap near all edges
            int sourceX = x + matrixX;
            int sourceY = y + matrixY;
    
            if (sourceX < 0)
              sourceX = 0;
    
            if (sourceX >= bitmap.Width)
              sourceX = bitmap.Width - 1;
    
            if (sourceY < 0)
              sourceY = 0;
    
            if (sourceY >= bitmap.Height)
              sourceY = bitmap.Height - 1;
    
            sum += source[x, y];
          }
        }
    
        // factor and clamp sum
    
        destination[x, y] = sum;
      }
    }
    

    You might need an extra loop to handle each color channel which need to be processed separately. I couldn't immediately see where in your code you might be doing that from all the cryptic variables.

    0 讨论(0)
提交回复
热议问题