使用5x5卷积矩阵读取或写入受保护的内存的平滑滤波器

时间:2015-03-17 23:47:34

标签: c# filter convolution unsafe smooth

所以我尝试使用带有不安全代码的C#进行平滑过滤

 public static bool Conv5x5(Bitmap b, double[,] m, int factor, int offset)
    {

        if (0 == factor)
            return false;

        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;
        int stride2 = stride * 2;
        int stride3 = stride * 3;
        int stride4 = stride * 4;
        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 * 3;
            int nWidth = b.Width - 4;
            int nHeight = b.Height - 4;

            int nPixel;

            for (int y = 0; y < nHeight; ++y)
            {
                for (int x = 0; x < nWidth; ++x)
                {
                    nPixel = Convert.ToInt32((((pSrc[4] * m[0, 0]) + (pSrc[9] * m[0, 1]) + (pSrc[14] * m[0, 2]) + (pSrc[19] * m[0, 3]) + (pSrc[24] * m[0, 4]) +
                    (pSrc[4 + stride] * m[1, 0]) + (pSrc[9 + stride] * m[1, 0]) + (pSrc[14 + stride] * m[1, 0]) + (pSrc[19 + stride] * m[1, 0]) + (pSrc[24 + stride] * m[1, 0]) +
                    (pSrc[4 + stride2] * m[2, 0]) + (pSrc[9 + stride2] * m[2, 1]) + (pSrc[14 + stride2] * m[2, 2]) + (pSrc[19 + stride2] * m[2, 3]) + (pSrc[24 + stride2] * m[2, 4]) +
                    (pSrc[4 + stride3] * m[3, 0]) + (pSrc[9 + stride3] * m[3, 1]) + (pSrc[14 + stride3] * m[3, 2]) + (pSrc[19 + stride3] * m[3, 3]) + (pSrc[24 + stride3] * m[3, 4]) +
                    (pSrc[4 + stride4] * m[4, 0]) + (pSrc[9 + stride4] * m[4, 1]) + (pSrc[14 + stride4] * m[4, 2]) + (pSrc[19 + stride4] * m[4, 3]) + (pSrc[24 + stride4] * m[4, 4])
                    ) / factor) + offset);

                    if (nPixel < 0) nPixel = 0;
                    if (nPixel > 255) nPixel = 255;

                    p[9 + stride] = (byte)nPixel;

                    nPixel = Convert.ToInt32((((pSrc[3] * m[0, 0]) + (pSrc[8] * m[0, 1]) + (pSrc[13] * m[0, 2]) + (pSrc[18] * m[0, 3]) + (pSrc[23] * m[0, 4]) +
                     (pSrc[3 + stride] * m[1, 0]) + (pSrc[8 + stride] * m[1, 0]) + (pSrc[13 + stride] * m[1, 0]) + (pSrc[18 + stride] * m[1, 0]) + (pSrc[23 + stride] * m[1, 0]) +
                     (pSrc[3 + stride2] * m[2, 0]) + (pSrc[8 + stride2] * m[2, 1]) + (pSrc[13 + stride2] * m[2, 2]) + (pSrc[18 + stride2] * m[2, 3]) + (pSrc[23 + stride2] * m[2, 4]) +
                     (pSrc[3 + stride3] * m[3, 0]) + (pSrc[8 + stride3] * m[3, 1]) + (pSrc[13 + stride3] * m[3, 2]) + (pSrc[18 + stride3] * m[3, 3]) + (pSrc[23 + stride3] * m[3, 4]) +
                     (pSrc[3 + stride4] * m[4, 0]) + (pSrc[8 + stride4] * m[4, 1]) + (pSrc[13 + stride4] * m[4, 2]) + (pSrc[18 + stride4] * m[4, 3]) + (pSrc[23 + stride4] * m[4, 4])
                     ) / factor) + offset);

                    if (nPixel < 0) nPixel = 0;
                    if (nPixel > 255) nPixel = 255;

                    p[8 + stride] = (byte)nPixel;

                    nPixel = Convert.ToInt32((((pSrc[2] * m[0, 0]) + (pSrc[7] * m[0, 1]) + (pSrc[12] * m[0, 2]) + (pSrc[17] * m[0, 3]) + (pSrc[22] * m[0, 4]) +
                     (pSrc[2 + stride] * m[1, 0]) + (pSrc[7 + stride] * m[1, 0]) + (pSrc[12 + stride] * m[1, 0]) + (pSrc[17 + stride] * m[1, 0]) + (pSrc[22 + stride] * m[1, 0]) +
                     (pSrc[2 + stride2] * m[2, 0]) + (pSrc[7 + stride2] * m[2, 1]) + (pSrc[12 + stride2] * m[2, 2]) + (pSrc[17 + stride2] * m[2, 3]) + (pSrc[22 + stride2] * m[2, 4]) +
                     (pSrc[2 + stride3] * m[3, 0]) + (pSrc[7 + stride3] * m[3, 1]) + (pSrc[12 + stride3] * m[3, 2]) + (pSrc[17 + stride3] * m[3, 3]) + (pSrc[22 + stride3] * m[3, 4]) +
                     (pSrc[2 + stride4] * m[4, 0]) + (pSrc[7 + stride4] * m[4, 1]) + (pSrc[12 + stride4] * m[4, 2]) + (pSrc[17 + stride4] * m[4, 3]) + (pSrc[22 + stride4] * m[4, 4])
                     ) / factor) + offset);

                    if (nPixel < 0) nPixel = 0;
                    if (nPixel > 255) nPixel = 255;

                    p[7 + stride] = (byte)nPixel;

                    nPixel = Convert.ToInt32((((pSrc[1] * m[0, 0]) + (pSrc[6] * m[0, 1]) + (pSrc[11] * m[0, 2]) + (pSrc[16] * m[0, 3]) + (pSrc[21] * m[0, 4]) +
                     (pSrc[1 + stride] * m[1, 0]) + (pSrc[6 + stride] * m[1, 0]) + (pSrc[11 + stride] * m[1, 0]) + (pSrc[16 + stride] * m[1, 0]) + (pSrc[21 + stride] * m[1, 0]) +
                     (pSrc[1 + stride2] * m[2, 0]) + (pSrc[6 + stride2] * m[2, 1]) + (pSrc[11 + stride2] * m[2, 2]) + (pSrc[16 + stride2] * m[2, 3]) + (pSrc[21 + stride2] * m[2, 4]) +
                     (pSrc[1 + stride3] * m[3, 0]) + (pSrc[6 + stride3] * m[3, 1]) + (pSrc[11 + stride3] * m[3, 2]) + (pSrc[16 + stride3] * m[3, 3]) + (pSrc[21 + stride3] * m[3, 4]) +
                     (pSrc[1 + stride4] * m[4, 0]) + (pSrc[6 + stride4] * m[4, 1]) + (pSrc[11 + stride4] * m[4, 2]) + (pSrc[16 + stride4] * m[4, 3]) + (pSrc[21 + stride4] * m[4, 4])
                     ) / factor) + offset);

                    if (nPixel < 0) nPixel = 0;
                    if (nPixel > 255) nPixel = 255;

                    p[6 + stride] = (byte)nPixel;

                    nPixel = Convert.ToInt32((((pSrc[0] * m[0, 0]) + (pSrc[5] * m[0, 1]) + (pSrc[10] * m[0, 2]) + (pSrc[15] * m[0, 3]) + (pSrc[20] * m[0, 4]) +
                     (pSrc[0 + stride] * m[1, 0]) + (pSrc[5 + stride] * m[1, 0]) + (pSrc[10 + stride] * m[1, 0]) + (pSrc[15 + stride] * m[1, 0]) + (pSrc[20 + stride] * m[1, 0]) +
                     (pSrc[0 + stride2] * m[2, 0]) + (pSrc[5 + stride2] * m[2, 1]) + (pSrc[10 + stride2] * m[2, 2]) + (pSrc[15 + stride2] * m[2, 3]) + (pSrc[20 + stride2] * m[2, 4]) +
                     (pSrc[0 + stride3] * m[3, 0]) + (pSrc[5 + stride3] * m[3, 1]) + (pSrc[10 + stride3] * m[3, 2]) + (pSrc[15 + stride3] * m[3, 3]) + (pSrc[20 + stride3] * m[3, 4]) +
                     (pSrc[0 + stride4] * m[4, 0]) + (pSrc[5 + stride4] * m[4, 1]) + (pSrc[10 + stride4] * m[4, 2]) + (pSrc[15 + stride4] * m[4, 3]) + (pSrc[20 + stride4] * m[4, 4])
                     ) / factor) + offset);

                    if (nPixel < 0) nPixel = 0;
                    if (nPixel > 255) nPixel = 255;

                    p[5 + stride] = (byte)nPixel;

                    p += 5;
                    pSrc += 5;
                }
                p += nOffset;
                pSrc += nOffset;
            }
        }

        b.UnlockBits(bmData);
        bSrc.UnlockBits(bmSrc);
        return true; 
    }

使用我的默认参数:

 public static double[,] Smooth5x5
    {
        get
        {
            return new double[,]  
            { { 1, 1, 1, 1, 1}, 
              { 1, 1, 1, 1, 1},
              { 1, 1, 1, 1, 1},
              { 1, 1, 1, 1, 1},
              { 1, 1, 1, 1, 1}, };
        }
    }
int factor=25; int offset=0;

我有这个错误: “附加信息:尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

所以,这是一个解决方案:此外,这里是所有卷积滤波器和所有卷积矩阵大小的通用卷积函数:

 public bool universalConv(Bitmap b, double[,] m, int factor, int offset, byte fill)
    {
        int convMatrixWidth = m.GetLength(0);
        int convMatrixHeight = m.GetLength(1);
        // Avoid divide by zero errors
        if (0 == factor)
            return false;

        Bitmap bSrc = new Bitmap(b.Width + convMatrixWidth - 1, b.Height + convMatrixHeight - 1, b.PixelFormat);
        bSrc = fillBitmapWith(bSrc, fill);
        Graphics g = Graphics.FromImage(bSrc);
        g.DrawImage(b, 0, 0, b.Width, b.Height);

        g.Dispose();

        // GDI+ still lies to us - the return format is BGR, NOT RGB.
        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;

        int stridetmp = bmSrc.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 * 3;
            int nOffsettmp = stridetmp - bSrc.Width * 3;
            int nWidth = b.Width;
            int nHeight = b.Height - convMatrixWidth / 2;

            int nPixel, nPixel2, nPixel3;

            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    nPixel = nPixel2 = nPixel3 = 0;
                    for (int i = 0; i < convMatrixHeight; i++)
                    {

                        for (int j = 0; j < convMatrixWidth; j++)
                        {
                            nPixel += Convert.ToInt32(pSrc[2 + (j * 3) + i * stridetmp] * m[i, j]);
                            nPixel2 += Convert.ToInt32(pSrc[1 + (j * 3) + i * stridetmp] * m[i, j]);
                            nPixel3 += Convert.ToInt32(pSrc[0 + (j * 3) + i * stridetmp] * m[i, j]);
                        }
                    }

                    nPixel = nPixel / factor + offset;
                    nPixel2 = nPixel2 / factor + offset;
                    nPixel3 = nPixel3 / factor + offset;

                    if (nPixel < 0) nPixel = 0;
                    if (nPixel > 255) nPixel = 255;

                    p[2 + stride * (convMatrixWidth / 2)] = (byte)nPixel;

                    if (nPixel2 < 0) nPixel2 = 0;
                    if (nPixel2 > 255) nPixel2 = 255;

                    p[1 + stride * (convMatrixWidth / 2)] = (byte)nPixel2;

                    if (nPixel3 < 0) nPixel3 = 0;
                    if (nPixel3 > 255) nPixel3 = 255;

                    p[0 + stride * (convMatrixWidth / 2)] = (byte)nPixel3;

                    p += 3;
                    pSrc += 3;
                }
                p += nOffset;
                pSrc += (nOffsettmp + (convMatrixWidth - 1) * 3);
            }
        }

        b.UnlockBits(bmData);
        bSrc.UnlockBits(bmSrc);

        return true;
    }