Fastest Sobel Edge Detection C#

前端 未结 1 1910
天命终不由人
天命终不由人 2021-02-06 18:03

I want to make a program that implements sobel edge detection. This is my code :

private Bitmap SobelEdgeDetect(Bitmap ori)
{
        Bitmap b = original;
               


        
1条回答
  •  长发绾君心
    2021-02-06 18:40

    You really need to use LockBits instead of GetPixel and SetPixel.

    So you create a BitmapData object that contains all of the pixel data:

    // lock the input bitmap's bits  
    System.Drawing.Imaging.BitmapData bmpData =
        original.LockBits(new Rectangle(0, 0, original.Width, original.Height), 
        System.Drawing.Imaging.ImageLockMode.Read, original.PixelFormat);
    

    Then, you can get the address of the first scan line (i.e. the first row of pixels):

    IntPtr ptr = bmpData.Scan0;
    

    Now you have two choices. If you're happy to mark your function as unsafe then you can access the pixels directly using pointer arithmetic, like this

    byte* pPixels = (byte*)ptr.ToPointer();
    

    which gives you a pointer to the first byte of an RGB pixel (assuming 24bpp). Then you can access an individual pixel at (x,y) using pointer arithmetic. First you determine how many bytes per pixel (if you don't already know)

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

    Then calculate the index to the pixel you want

    byte* pPixelAtXY = pPixels + (y * bmpData.Stride) + (x * nBytesPerPixel);
    

    This gives you unsafe access to the pixels in a Bitmap which you can do for the input and output bitmaps for fastest speed. Note that to use unsafe code, you need to mark your function as unsafe and edit your project properties.

    If you don't want to use unsafe code, you can still speed things up by copying all of the pixel data to a byte array before processing and then copy it back afterwards. As the MSDN example showed

    // Get the address of the first line.
    IntPtr ptr = bmpData.Scan0;
    
    // Declare an array to hold the bytes of the bitmap. 
    int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
    byte[] rgbValues = new byte[bytes];
    
    // Copy the RGB values into the array.
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
    
    // Set every third value to 255. A 24bpp bitmap will look red.   
    for (int counter = 2; counter < rgbValues.Length; counter += 3)
        rgbValues[counter] = 255;
    
    // Copy the RGB values back to the bitmap
    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
    

    Whichever method you use, when you have finished with the pixel data, you must release it using UnlockBits

    original.UnlockBits(bmpData);
    

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