Почему этот детектор края не работает правильно, если ширина растрового изображения не делится на 4? - PullRequest
2 голосов
/ 27 мая 2020
• 1000 ords (80,80) в этом случае разбивается и размещается неправильно. Почему это так и как заставить код работать с любой шириной растрового изображения?
        private Bitmap SobelEdgeDetect2(Bitmap original, byte Threshold = 128)
    {

        // https://stackoverflow.com/questions/16747257/edge-detection-with-lockbits-c-sharp

        int width = original.Width;
        int height = original.Height;

        int BitsPerPixel = Image.GetPixelFormatSize(original.PixelFormat);
        int OneColorBits = BitsPerPixel / 8;

        BitmapData bmpData = original.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, original.PixelFormat);
        int position;
        int[,] gx = new int[,] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };
        int[,] gy = new int[,] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } };

        Bitmap dstBmp = new Bitmap(width, height, original.PixelFormat);
        BitmapData dstData = dstBmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, dstBmp.PixelFormat);

        int byteCount = dstData.Stride * dstBmp.Height;          
        byte[] input = new byte[byteCount];
        byte[] processed = new byte[byteCount];
        IntPtr ptr = bmpData.Scan0;
        IntPtr dst = dstData.Scan0;
        Marshal.Copy(ptr, input, 0, input.Length);
        Marshal.Copy(dst,processed, 0, input.Length);

        int BlackPoints = 0;
        int WhitePoints = 0;

        for (int i = 1; i < height - 1; i++) // y
        {
            for (int j = 1; j < width - 1; j++)  // x 
                 {
                int NewX = 0, NewY = 0;

                for (int ii = 0; ii < 3; ii++)
                {
                    for (int jj = 0; jj < 3; jj++)
                    {
                        int I = i + ii - 1;
                        int J = j + jj - 1;

                            byte Current = input[(I * (width) + J) * OneColorBits];
                            NewX += gx[ii, jj] * Current;
                            NewY += gy[ii, jj] * Current;                            
                    }
                }
                position = (i * (width) + j) * OneColorBits;

                if (NewX * NewX + NewY * NewY > Threshold * Threshold)
                {
                    processed[position] = 255;
                    processed[position + 1] = 255;
                    processed[position + 2] = 255;
                    WhitePoints++;
                }
                else
                {
                    processed[position] = 0;
                    processed[position + 1] = 0;
                    processed[position + 2] = 0;
                    BlackPoints++;
                }

                if (j >= 78 && j <= 82 && i >= 78 && i <= 82)
                {
                    processed[position] = 0;
                    processed[position + 1] = 0;
                    processed[position + 2] = 255;
                }

            }

        }

        Marshal.Copy(processed, 0, dst, input.Length);
        dstBmp.UnlockBits(dstData);

        return dstBmp;
    }

1 Ответ

0 голосов
/ 29 мая 2020

Для растрового изображения шириной 201 пиксель dstData.Stride было 604. Для растрового изображения шириной 200 пиксель dstData.Stride было 612, что объясняет, почему для моего кода ширина должна была делиться на 4.

Замена

position = (i * (width) + j) * OneColorBits;

от

position = i * dstData.Stride + j * OneColorBits;

и

byte Current = input[(I * (width) + J) * OneColorBits];

от

byte Current = input[I * dstData.Stride + J * OneColorBits];

Устранена проблема.

...