最快的Sobel边缘检测C# [英] Fastest Sobel Edge Detection C#

查看:1241
本文介绍了最快的Sobel边缘检测C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个实现sobel边缘检测的程序。
这是我的代码:

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

private Bitmap SobelEdgeDetect(Bitmap ori)
{
        Bitmap b = original;
        Bitmap bb = original;
        int width = b.Width;
        int height = b.Height;
        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 } };

        int[,] allPixR = new int[width, height];
        int[,] allPixG = new int[width, height];
        int[,] allPixB = new int[width, height];

        int limit = 128 * 128;

        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                allPixR[i, j] = b.GetPixel(i, j).R;
                allPixG[i, j] = b.GetPixel(i, j).G;
                allPixB[i, j] = b.GetPixel(i, j).B;
            }
        }

        int new_rx = 0, new_ry = 0;
        int new_gx = 0, new_gy = 0;
        int new_bx = 0, new_by = 0;
        int rc, gc, bc;
        for (int i = 1; i < b.Width - 1; i++)
        {
            for (int j = 1; j < b.Height - 1; j++)
            {

                new_rx = 0;
                new_ry = 0;
                new_gx = 0;
                new_gy = 0;
                new_bx = 0;
                new_by = 0;
                rc = 0;
                gc = 0;
                bc = 0;

                for (int wi = -1; wi < 2; wi++)
                {
                    for (int hw = -1; hw < 2; hw++)
                    {
                        rc = allPixR[i + hw, j + wi];
                        new_rx += gx[wi + 1, hw + 1] * rc;
                        new_ry += gy[wi + 1, hw + 1] * rc;

                        gc = allPixG[i + hw, j + wi];
                        new_gx += gx[wi + 1, hw + 1] * gc;
                        new_gy += gy[wi + 1, hw + 1] * gc;

                        bc = allPixB[i + hw, j + wi];
                        new_bx += gx[wi + 1, hw + 1] * bc;
                        new_by += gy[wi + 1, hw + 1] * bc;
                    }
                }
                if (new_rx * new_rx + new_ry * new_ry > limit || new_gx * new_gx + new_gy * new_gy > limit || new_bx * new_bx + new_by * new_by > limit)
                    bb.SetPixel(i, j, Color.Black);

                //bb.SetPixel (i, j, Color.FromArgb(allPixR[i,j],allPixG[i,j],allPixB[i,j]));
                else
                    bb.SetPixel(i, j, Color.Transparent);
            }
        }
        return bb;

  }

我想要使用lockbits,所以我的程序可以运行得更快,但我实际上还不知道如何使用它。
可以给任何人提供一些解释或示例代码吗?

i want to using lockbits so my program can run faster, but i actually still not understand how to use it. could anyone give some explanation or example code?

推荐答案

您真的需要使用 LockBits 而不是 GetPixel SetPixel

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

因此,您可以创建包含所有像素数据的 BitmapData 对象:

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;

现在您有两种选择。如果您很乐意将您的函数标记为 unsafe ,那么您可以使用指针算法直接访问像素,如

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();

给你一个指向RGB像素的第一个字节的指针(假设为24bpp)。然后,您可以使用指针算法访问(x,y)中的单个像素。首先你确定每个像素有多少字节(如果你还不知道的话)

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.

如果您不想使用不安全代码,您仍然可以加速通过在处理之前将所有像素数据复制到字节数组然后将其复制回来。正如MSDN示例所示:

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

无论使用什么方法,当您完成像素数据时,您必须 释放它使用 UnlockBits

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

original.UnlockBits(bmpData);

这篇关于最快的Sobel边缘检测C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆