Фильтр C # Cvolution для матрицы любого размера (1×1, 3×3, 5×5, …) не применяется полностью

Я делаю фильтр свертки для своего проекта, и мне удалось сделать его для любого размера матрицы, но по мере того, как он становится больше, я заметил, что не все биты изменены. Вот фотографии, показывающие проблему:

Первый – это оригинал введите описание изображения здесь Фильтр: размытие 9×9

Фильтр: EdgeDetection 9×9: введите описание изображения здесь

Как вы можете видеть, есть небольшая полоска, которая никогда не изменяется, и по мере увеличения матрицы полоса также становится больше (в 3х3 она не была видна)

Мой class матриц свертки:

public class ConvMatrix { public int Factor = 1; public int Height, Width; public int Offset = 0; public int[,] Arr; //later I assign functions to set these variables ... } 

Функция фильтра:

  Bitmap Conv3x3(Bitmap b, ConvMatrix m) { if (0 == m.Factor) return b; Bitmap bSrc = (Bitmap)b.Clone(); BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bmData.Stride; System.IntPtr Scan0 = bmData.Scan0; System.IntPtr SrcScan0 = bmSrc.Scan0; unsafe { byte* p = (byte*)(void*)Scan0; byte* pSrc = (byte*)(void*)SrcScan0; int nOffset = stride - b.Width * m.Width; int nWidth = b.Width - (m.Size-1); int nHeight = b.Height - (m.Size-2); int nPixel = 0; for (int y = 0; y < nHeight; y++) { for (int x = 0; x < nWidth; x++) { for (int r = 0; r < m.Height; r++) { nPixel = 0; for (int i = 0; i < m.Width; i++) for (int j = 0; j < m.Height; j++) { nPixel += (pSrc[(m.Width * (i + 1)) - 1 - r + stride * j] * m.Arr[j, i]); } nPixel /= m.Factor; nPixel += m.Offset; if (nPixel  255) nPixel = 255; p[(m.Width * (m.Height / 2 + 1)) - 1 - r + stride * (m.Height / 2)] = (byte)nPixel; } p += m.Width; pSrc += m.Width; } p += nOffset; pSrc += nOffset; } } b.UnlockBits(bmData); bSrc.UnlockBits(bmSrc); return b; } 

Пожалуйста помоги

    Проблема в том, что ваш код явно останавливается за пределами краев. Расчет пределов для ваших внешних циклов ( nWidth и nHeight ) не должен включать размер матрицы, они должны быть равны размеру вашего растрового изображения.

    Когда вы это сделаете, если вы представляете, что происходит, когда вы кладете центральную точку вашей матрицы на каждый пиксель в этом случае (потому что вам нужно читать со всех размеров пикселя), matrix будет частично находиться за пределами изображения вблизи краев ,

    Существует несколько подходов к тому, что делать вблизи краев, но разумным является закрепить координаты по краям. То есть, когда вы закончите чтение пикселя извне растрового изображения, просто получите ближайший пиксель от края (размер или угол).

    Я также не понимаю, зачем вам пять циклов – вы, кажется, зацикливаете по высоте матрицы дважды. Это не выглядит правильным. В общем, общая структура должна быть примерно такой:

     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; } } 

    Вам может понадобиться дополнительный цикл для обработки каждого цветового канала, который необходимо обрабатывать отдельно. Я не мог сразу увидеть, где в вашем коде вы могли бы это сделать из всех загадочных переменных.