如何在 Windows Phone 8 中对图像执行边缘检测
本文关键字:图像 执行 边缘检测 Windows Phone | 更新日期: 2023-09-27 18:31:57
我是图像处理的新手,想在我的应用程序中实现边缘检测功能。在看了几个例子之后,Sobel 3x3 方法脱颖而出,成为我想尝试的方法。我引用了 http://code.msdn.microsoft.com/wpapps/Image-Edge-Detection-5c5a0dc2 但System.Drawing
在Windows Phone中不存在。我不知道如何根据我的目的修改示例。我一直在使用WriteableBitmapEx进行一些图像效果,通过直接修改argb像素数据的值。有没有办法为Sobel边缘检测方法做到这一点?
索贝尔.cs
public string Name { get { return "Sobel"; } }
public Sobel()
{
}
/// <returns>The result of WriteabelBitmap processing.</returns>
public WriteableBitmap Process(WriteableBitmap input)
{
// Prepare some variables
var width = input.PixelWidth;
var height = input.PixelHeight;
return Process(input.Pixels, width, height).ToWriteableBitmap(width, height);
}
/// <returns>The result of the processing.</returns>
public int[] Process(int[] inputPixels, int width, int height)
{
WriteableBitmap output = ExtBitmap.ConvolutionFilter(inputPixels.ToWriteableBitmap(width, height), Matrix.Sobel3x3Horizontal,
Matrix.Sobel3x3Vertical,
1.0, 0, false);
return output.Pixels;
}
矩阵.cs
public static double[,] Sobel3x3Horizontal
{
get
{
return new double[,]
{ { -1, 0, 1, },
{ -2, 0, 2, },
{ -1, 0, 1, }, };
}
}
public static double[,] Sobel3x3Vertical
{
get
{
return new double[,]
{ { 1, 2, 1, },
{ 0, 0, 0, },
{ -1, -2, -1, }, };
}
}
ExtBitmap.cs(我从代码示例中的粗略实现)
public static class ExtBitmap
{
private static WriteableBitmap ConvolutionFilter(WriteableBitmap sourceBitmap,
double[,] filterMatrix,
double factor = 1,
int bias = 0,
bool grayscale = false)
{
//BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0,
// sourceBitmap.PixelWidth, sourceBitmap.PixelHeight),
// ImageLockMode.ReadOnly,
// PixelFormat.Format32bppArgb);
byte[] pixelBuffer = new byte[sourceBitmap.Pixels.Count()];
byte[] resultBuffer = new byte[sourceBitmap.Pixels.Count()];
//Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
//sourceBitmap.UnlockBits(sourceData);
if (grayscale == true)
{
float rgb = 0;
for (int k = 0; k < pixelBuffer.Length; k += 4)
{
rgb = pixelBuffer[k] * 0.11f;
rgb += pixelBuffer[k + 1] * 0.59f;
rgb += pixelBuffer[k + 2] * 0.3f;
pixelBuffer[k] = (byte)rgb;
pixelBuffer[k + 1] = pixelBuffer[k];
pixelBuffer[k + 2] = pixelBuffer[k];
pixelBuffer[k + 3] = 255;
}
}
double blue = 0.0;
double green = 0.0;
double red = 0.0;
int filterWidth = filterMatrix.GetLength(1);
int filterHeight = filterMatrix.GetLength(0);
int filterOffset = (filterWidth - 1) / 2;
int calcOffset = 0;
int byteOffset = 0;
for (int offsetY = filterOffset; offsetY <
sourceBitmap.PixelHeight - filterOffset; offsetY++)
{
for (int offsetX = filterOffset; offsetX <
sourceBitmap.PixelWidth - filterOffset; offsetX++)
{
blue = 0;
green = 0;
red = 0;
byteOffset = offsetY *
sourceBitmap.PixelWidth +
offsetX * 4;
for (int filterY = -filterOffset;
filterY <= filterOffset; filterY++)
{
for (int filterX = -filterOffset;
filterX <= filterOffset; filterX++)
{
calcOffset = byteOffset +
(filterX * 4) +
(filterY * sourceBitmap.PixelWidth);
blue += (double)(pixelBuffer[calcOffset]) *
filterMatrix[filterY + filterOffset,
filterX + filterOffset];
green += (double)(pixelBuffer[calcOffset + 1]) *
filterMatrix[filterY + filterOffset,
filterX + filterOffset];
red += (double)(pixelBuffer[calcOffset + 2]) *
filterMatrix[filterY + filterOffset,
filterX + filterOffset];
}
}
blue = factor * blue + bias;
green = factor * green + bias;
red = factor * red + bias;
if (blue > 255)
{ blue = 255; }
else if (blue < 0)
{ blue = 0; }
if (green > 255)
{ green = 255; }
else if (green < 0)
{ green = 0; }
if (red > 255)
{ red = 255; }
else if (red < 0)
{ red = 0; }
resultBuffer[byteOffset] = (byte)(blue);
resultBuffer[byteOffset + 1] = (byte)(green);
resultBuffer[byteOffset + 2] = (byte)(red);
resultBuffer[byteOffset + 3] = 255;
}
}
WriteableBitmap resultBitmap = new WriteableBitmap(sourceBitmap.PixelWidth, sourceBitmap.PixelHeight);
//BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0,
// resultBitmap.Width, resultBitmap.Height),
// ImageLockMode.WriteOnly,
// PixelFormat.Format32bppArgb);
//Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
//resultBitmap.UnlockBits(resultData);
return resultBitmap;
}
public static WriteableBitmap ConvolutionFilter(this WriteableBitmap sourceBitmap,
double[,] xFilterMatrix,
double[,] yFilterMatrix,
double factor = 1,
int bias = 0,
bool grayscale = false)
{
//BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0,
// sourceBitmap.Width, sourceBitmap.Height),
// ImageLockMode.ReadOnly,
// PixelFormat.Format32bppArgb);
byte[] pixelBuffer = new byte[sourceBitmap.Pixels.Count()];
byte[] resultBuffer = new byte[sourceBitmap.Pixels.Count()];
//Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
//sourceBitmap.UnlockBits(sourceData);
if (grayscale == true)
{
float rgb = 0;
for (int k = 0; k < pixelBuffer.Length; k += 4)
{
rgb = pixelBuffer[k] * 0.11f;
rgb += pixelBuffer[k + 1] * 0.59f;
rgb += pixelBuffer[k + 2] * 0.3f;
pixelBuffer[k] = (byte)rgb;
pixelBuffer[k + 1] = pixelBuffer[k];
pixelBuffer[k + 2] = pixelBuffer[k];
pixelBuffer[k + 3] = 255;
}
}
double blueX = 0.0;
double greenX = 0.0;
double redX = 0.0;
double blueY = 0.0;
double greenY = 0.0;
double redY = 0.0;
double blueTotal = 0.0;
double greenTotal = 0.0;
double redTotal = 0.0;
int filterOffset = 1;
int calcOffset = 0;
int byteOffset = 0;
for (int offsetY = filterOffset; offsetY <
sourceBitmap.PixelHeight - filterOffset; offsetY++)
{
for (int offsetX = filterOffset; offsetX <
sourceBitmap.PixelWidth - filterOffset; offsetX++)
{
blueX = greenX = redX = 0;
blueY = greenY = redY = 0;
blueTotal = greenTotal = redTotal = 0.0;
byteOffset = offsetY *
sourceBitmap.PixelWidth +
offsetX * 4;
for (int filterY = -filterOffset;
filterY <= filterOffset; filterY++)
{
for (int filterX = -filterOffset;
filterX <= filterOffset; filterX++)
{
calcOffset = byteOffset +
(filterX * 4) +
(filterY * sourceBitmap.PixelWidth);
blueX += (double)(pixelBuffer[calcOffset]) *
xFilterMatrix[filterY + filterOffset,
filterX + filterOffset];
greenX += (double)(pixelBuffer[calcOffset + 1]) *
xFilterMatrix[filterY + filterOffset,
filterX + filterOffset];
redX += (double)(pixelBuffer[calcOffset + 2]) *
xFilterMatrix[filterY + filterOffset,
filterX + filterOffset];
blueY += (double)(pixelBuffer[calcOffset]) *
yFilterMatrix[filterY + filterOffset,
filterX + filterOffset];
greenY += (double)(pixelBuffer[calcOffset + 1]) *
yFilterMatrix[filterY + filterOffset,
filterX + filterOffset];
redY += (double)(pixelBuffer[calcOffset + 2]) *
yFilterMatrix[filterY + filterOffset,
filterX + filterOffset];
}
}
blueTotal = Math.Sqrt((blueX * blueX) + (blueY * blueY));
greenTotal = Math.Sqrt((greenX * greenX) + (greenY * greenY));
redTotal = Math.Sqrt((redX * redX) + (redY * redY));
if (blueTotal > 255)
{ blueTotal = 255; }
else if (blueTotal < 0)
{ blueTotal = 0; }
if (greenTotal > 255)
{ greenTotal = 255; }
else if (greenTotal < 0)
{ greenTotal = 0; }
if (redTotal > 255)
{ redTotal = 255; }
else if (redTotal < 0)
{ redTotal = 0; }
resultBuffer[byteOffset] = (byte)(blueTotal);
resultBuffer[byteOffset + 1] = (byte)(greenTotal);
resultBuffer[byteOffset + 2] = (byte)(redTotal);
resultBuffer[byteOffset + 3] = 255;
}
}
WriteableBitmap resultBitmap = new WriteableBitmap(sourceBitmap.PixelWidth, sourceBitmap.PixelHeight);
//BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0,
// resultBitmap.Width, resultBitmap.Height),
// ImageLockMode.WriteOnly,
// PixelFormat.Format32bppArgb);
//Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
//resultBitmap.UnlockBits(resultData);
return resultBitmap;
}
}
你应该尝试WriteableBitmapEx及其卷积过滤器。只需提供一个适当的卷积矩阵,您就可以开始了。它已经带有其中的 3 个,因此应该很容易适应。请参阅此处的源代码文件:
https://writeablebitmapex.codeplex.com/SourceControl/latest#trunk/Source/WriteableBitmapEx/WriteableBitmapFilterExtensions.cs
AForge.Net 框架带有一堆过滤器,其中包括Sobel边缘检测器。它使用起来非常简单,您只需实例化一个SobelEdgeDetector并在图像上调用其App或ApplyInPlace方法。
http://www.aforgenet.com/framework/docs/html/2c8218cc-921c-34d8-5c88-39c652488490.htm