首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Sobel算子&与WriteableBitmapEx卷积

Sobel算子&与WriteableBitmapEx卷积
EN

Stack Overflow用户
提问于 2013-02-12 15:48:03
回答 2查看 3.7K关注 0票数 3

所以我在Windows上使用WriteableBitmapEx作为应用程序。我试着用sobel算子对图像进行边缘检测。我已经使用.Convolute()成功地将用于x和y检测的两个内核应用到图像上,但现在我不得不将这两个图像添加到其中一个。问题是,这两个图像的所有像素似乎都具有0的透明度值(因此,在ARGB中的A)。我可以在没有问题的情况下单独显示这两个图像,但是添加它们只会给我一张黑色的图片。所以我的问题是:

  • 为什么在卷积后每个像素的透明度设置为0?
  • 为什么我仍然可以显示图像而不全是黑色的?
  • 为什么当我添加两个图像时,它是黑色的?
  • 是否有更好的方法将两个图像结合起来?Blit不幸的人似乎不支持这种像素加法。但ForEach真的很慢..。

到目前为止,这是我的代码。我可以同时显示wbmpY和wbmpX,但是finalbmp完全是黑色的。

代码语言:javascript
复制
    public int[,] sobelY = new int[3, 3] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } };
    public int[,] sobelX = new int[3, 3] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };

    public void trim(WriteableBitmap wbmp)
    {
        var graybmp = wbmp.Clone();
        graybmp.ForEach(toGrayscale);

        var wbmpY = graybmp.Clone();
        var wbmpX = graybmp.Clone();

        wbmpY = wbmpY.Convolute(sobelY, 1, 0);
        wbmpX = wbmpX.Convolute(sobelX, 1, 0);

        var finalbmp = combineSobel(wbmpX, wbmpY);           
     }

    public WriteableBitmap combineSobel(WriteableBitmap img, WriteableBitmap img2)
    {
        int height = img.PixelHeight;
        int width = img.PixelWidth;
        WriteableBitmap result = img.Clone();
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                Color imgColor = img.GetPixel(x, y);
                Color img2Color = img2.GetPixel(x, y);
                Color newColor = Color.FromArgb(
                    Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.A, 2) + Math.Pow(img2Color.A, 2)), (byte)255),
                    Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.R, 2) + Math.Pow(img2Color.R, 2)), (byte)255),
                    Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.G, 2) + Math.Pow(img2Color.G, 2)), (byte)255),
                    Math.Min((byte)Math.Sqrt(Math.Pow(imgColor.B, 2) + Math.Pow(img2Color.B, 2)), (byte)255)
                );

                result.SetPixel(x, y, newColor);
            }
        }
        return result;
    }
EN

回答 2

Stack Overflow用户

发布于 2013-02-20 16:02:47

是否有更好的方法将两个图像结合起来?布利特厄运利似乎不支持这种像素加法.但ForEach真的很慢..。

为此,您应该使用不安全的代码,请查看以下内容:Why is my unsafe code block slower than my safe code?

就速度而言,考虑一下为每个像素调用16个函数(4xMath.Min、4xMath.Pow、4xMath.Sqrt)。这是一个巨大的开销。

像素值在0,255 Math.Pow(0,255,2) + Mat.Pow(0,255,2)范围内,结果是0,2*Math.Pow(255,2) => 0,130 050 i将构造如下的查找表:

代码语言:javascript
复制
byte[] LUT4Sqrt = new byte[130051];

for (int i = 0; i < 130051; i++)
{
    LUT4Sqrt[i] = (byte)(Math.Sqrt(i));
}

Math.Pow的查找表也可以制作。

票数 1
EN

Stack Overflow用户

发布于 2013-02-17 22:23:16

代码中有两个问题:

1)我试过了,而卷积法对我不起作用--它只是创造了一个空的图像。我想这不是你的错。当你组合两个空图像时,你会得到一个空的。

2)合并实现有一个小问题。您可以在不使用sqrt的情况下将透明度设置为255,就像在r,g,b上所做的那样。

希望这能帮上忙

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14836299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档