最快的Sobel边缘检测C#

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

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  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,所以我的程序可以运行得更快,但我实际上仍然不明白如何使用它。 谁能给出一些解释或示例代码?

您确实需要使用LockBits而不是GetPixelSetPixel

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

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

然后,您可以获取第一条扫描线的地址(即第一行像素):

 IntPtr ptr = bmpData.Scan0; 

现在你有两个选择。 如果您很高兴将您的function标记为unsafe那么您可以使用指针算法直接访问像素,就像这样

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

它为您提供指向RGB像素的第一个字节的指针(假设为24bpp)。 然后,您可以使用指针算法访问(x,y)处的单个像素。 首先确定每个像素的字节数(如果您还不知道)

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

然后计算所需像素的索引

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

这使您可以unsafe访问Bitmap的像素,您可以对输入和输出位图执行以获得最快速度。 请注意,要使用不安全的代码,您需要将您的函数标记为不安全并编辑项目属性 。

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

 // 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释放它

 original.UnlockBits(bmpData);