[英]Fastest Sobel Edge Detection 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 < 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
代替GetPixel
和SetPixel
。
因此,您将创建一个包含所有像素数据的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;
现在,您有两个选择。 如果您乐意将函数标记为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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.