简体   繁体   English

为什么我自己在 C# 中的广义卷积代码不起作用?

[英]why my own generalized convolution code in C# not working?

I am trying to create my own generalize convolution code using c# with unsafe block.我正在尝试使用带有 unsafe 块的 c# 创建我自己的泛化卷积代码。 The idea is to pass the image and the 2D kernel to the convolution function.想法是将图像和2D内核传递给卷积函数。 However, the code works -not sure properly- for 3x3 kernel, but it always give me an error (Attempted to read or write protected memory. This is often an indication that other memory is corrupt.) for 5x5 or 7x7 kernels.但是,对于 3x3 内核,该代码可以正常工作 - 不确定是否正确,但是对于 5x5 或 7x7 内核,它总是给我一个错误(尝试读取或写入受保护的内存。这通常表明其他内存已损坏。)。 Therefore, if anyone can help with this code but if you please do not give me some ready code (I already have it and it is working from internet).因此,如果有人可以帮助使用此代码,但请不要给我一些现成的代码(我已经有了它并且它可以从互联网上运行)。 what I want is to have my own understanding of my own code.我想要的是对自己的代码有自己的理解。 kindly, please help me to make my code works properly.好心,请帮助我使我的代码正常工作。

    public static bool convolveMy(Bitmap img, double[][] kernel)
    {
        Bitmap bSrc = (Bitmap)img.Clone();
        BitmapData bmdata = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
        BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, img.Width, img.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* pc = (byte*)(void*)SrcScan0;

            int nOffset = stride - img.Width * kernel.GetLength(0);
            int foff = (kernel.GetLength(0) - 1) / 2;

            for (int y = 1; y < img.Height -1 /*foff*/; y++)
                for (int x = 1; x < img.Width - 1/*foff*/; x++)
                {
                    double[][] bluem = new double[kernel.GetLength(0)][];
                    for (int i = 0; i < kernel.GetLength(0); i++)
                        bluem[i] = new double[kernel.GetLength(0)];
                    double[][] greenm = new double[kernel.GetLength(0)][];
                    for (int i = 0; i < kernel.GetLength(0); i++)
                        greenm[i] = new double[kernel.GetLength(0)];
                    double[][] redm = new double[kernel.GetLength(0)][];
                    for (int i = 0; i < kernel.GetLength(0); i++)
                        redm[i] = new double[kernel.GetLength(0)];

                    //The code below move the pixel components (RGB) to a new array 
                    int StrideMoveOverImg = 0;
                    int moveCountertoNextPixel = 0;
                    int kernelLength = kernel.GetLength(0);
                    for (int fy = 0; fy < kernel.GetLength(0); fy++)
                    {
                        for (int fx = 0; fx < kernel.GetLength(0); fx++)
                        {
                                bluem[fy][fx] = pc[moveCountertoNextPixel + StrideMoveOverImg];
                                ++moveCountertoNextPixel;
                                greenm[fy][fx] = pc[moveCountertoNextPixel + StrideMoveOverImg];
                                ++moveCountertoNextPixel;
                                redm[fy][fx] = pc[moveCountertoNextPixel + StrideMoveOverImg];
                                ++moveCountertoNextPixel;
                        }
                        moveCountertoNextPixel = 0;
                        StrideMoveOverImg += stride;
                    }
                    double cblueSum = 0;
                    double cgreenSum = 0;
                    double credSum = 0;
                    double cblue = 0;
                    double cgreen = 0;
                    double cred = 0;
                    //The code below start multiply the kernel with the image component 
                    //then the final value of the result pixel stored int cblueSum,CgreenSum and CredSum
                    for (int fy = -foff; fy <= foff; fy++)
                    {
                        for (int fx = -foff; fx <= foff; fx++)
                        {
                            cblue = bluem[fy + foff][fx + foff] * kernel[fy + foff][fx + foff];
                            cgreen = greenm[fy + foff][fx + foff] * kernel[fy + foff][fx + foff];
                            cred = redm[fy + foff][fx + foff] * kernel[fy + foff][fx + foff];
                            cblueSum += cblue;
                            cgreenSum += cgreen;
                            credSum += cred;
                        }
                    }
                    //check the result pixel : cBlueSum, CgreenSum,credSum is in the range of pixel value [0:255]
                    if (cblueSum < 0) cblueSum = 0;
                    if (cblueSum > 255) cblueSum = 255;
                    if (cgreenSum < 0) cgreenSum = 0;
                    if (cgreenSum > 255) cgreenSum = 255;
                    if (credSum < 0) credSum = 0;
                    if (credSum > 255) credSum = 255;

                    p[kernel.GetLength(0) + stride] = (byte)cblueSum;
                    p[kernel.GetLength(0) + 1 + stride] = (byte)cgreenSum;
                    p[kernel.GetLength(0) + 2 + stride] = (byte)credSum;

                    p  += kernel.GetLength(0);
                    pc += kernel.GetLength(0);
                }
           p += nOffset;
           pc += nOffset;
        }//unsafe
        img.UnlockBits(bmdata);
        bSrc.UnlockBits(bmSrc);
        return true;
    }

Finally, the code works .最后,代码有效。 Thank you All for helping.谢谢大家的帮助。 What I did is a simple mistake.我所做的是一个简单的错误。 I thought that the pointer (p) and (pc) should increase by the kernel width.我认为指针 (p) 和 (pc) 应该增加内核宽度。 However, the right way is to increase the pointer by the number of bytes inside the pixel and since am using 24byte image therefore I should increase the pointers by 3 so: change the code pc += kernel.GetLength(0);但是,正确的方法是将指针增加像素内的字节数,并且由于我使用的是 24 字节图像,因此我应该将指针增加 3,因此:更改代码 pc += kernel.GetLength(0); and p += kernel.GetLength(0);和 p += kernel.GetLength(0); to be p += 3;为 p += 3; and pc+=3 .和 pc+=3 。 again thank you all for help .再次感谢大家的帮助。 BTW if you have any comments or you find that the code may not work properly for any reason please please come up with comments顺便说一句,如果您有任何意见或发现代码可能因任何原因无法正常工作,请提出意见

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM