如何在 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;
    }
}

如何在 Windows Phone 8 中对图像执行边缘检测

你应该尝试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