【问题标题】:Sobel Edge Detection output for 16bit grayscale image16 位灰度图像的 Sobel 边缘检测输出
【发布时间】:2015-01-02 04:49:25
【问题描述】:

我在 C++ 和 C# 中看到了许多 Sobel 边缘检测操作,但我在将代码转换为在 16 位图形上操作时遇到了很大的困难。我见过的大部分代码都被编程为在 R.G.B 风格的位图上运行。我拥有的图形在一个 ushort[] 数组中,每行都有强度值,col 像素。

以下是我得出的代码:(问题是,它不太工作......)有了一个软糖因素,它可能正在寻找边缘,但它也发现了很多噪音。

但是,如果我将原始文件保存为 JPG,并将其运行到另一个接受位图的替代 Sobel-Edge-Detector C# 代码中,它会好很多...几乎没有噪音!我的 16 位灰度版本不应该更好吗?但这一定是我的代码达不到标准。我不明白其中的逻辑。

    public void sobel()
    {

        ushort[] pixels = new ushort[9];
        ushort[,] imageData = image_array[0].GetArray();
        ushort[,] imageOut = (ushort[,])imageData.Clone();
        uint xDim = (ushort)(imageData.GetLength(1) - imageData.GetLength(1) % regions);
        uint yDim = (ushort)(imageData.GetLength(0) - imageData.GetLength(0) % regions);

        double intensityX = 0.0;
        double intensityY = 0.0;
        double intensityTotal = 0.0;
        int limit = 1000000; //Just arbitrary junk number

        int filterOffset = 1;

        for (int offsetY = filterOffset; offsetY <
            yDim - (filterOffset+1); offsetY++)
        {

            for (int offsetX = filterOffset; offsetX <
                xDim - (filterOffset+1); offsetX++)
            {
                //intensityX = intensityY = 0;
                //intensityTotal = 0;

                pixels[0] = imageData[offsetY - 1, offsetX - 1];
                pixels[1] = imageData[offsetY - 1, offsetX];
                pixels[2] = imageData[offsetY - 1, offsetX + 1];
                pixels[3] = imageData[offsetY, offsetX - 1];
                pixels[4] = imageData[offsetY, offsetX];
                pixels[5] = imageData[offsetY, offsetX + 1];
                pixels[6] = imageData[offsetY + 1, offsetX - 1];
                pixels[7] = imageData[offsetY + 1, offsetX];
                pixels[8] = imageData[offsetY + 1, offsetX + 1];

                intensityX = pixels[8] + 2 * pixels[5] + pixels[2] - pixels[0] - 2 * pixels[3] - pixels[6];
                intensityY = pixels[8] + 2 * pixels[7] + pixels[6] - pixels[2] - 2 * pixels[1] - pixels[0];

                //intensityTotal = Math.Sqrt((intensityX * intensityX) + (intensityY * intensityY));
                //intensityTotal = Math.Abs(intensityX) + Math.Abs(intensityY);
                intensityTotal = intensityX * intensityX + intensityY * intensityY;
                //int sobel = (int)Math.Sqrt((xSobel * xSobel) + (ySobel * ySobel));

                //if (intensityTotal > MaximumValue)
                  //  intensityTotal = MaximumValue; //Presumably Black

                //if (intensityTotal < -1000) //1000 fudgefactor ...still not working correctly
                  //  intensityTotal = MinimumValue; //Presumably White
                //if (intensityTotal < (MinimumValue - 1000))
                  //  intensityTotal = MaximumValue;

                if (intensityTotal > limit)
                    imageOut[offsetY, offsetX] = MinimumValue;
                else
                    imageOut[offsetY, offsetX] = MaximumValue;

                //imageOut[offsetY, offsetX] = (ushort)intensityTotal;
            }

        }

        SetImageArrayItem(ImageDataIndex.RAWData, new DiskBackedArray(imageOut));

    }

假设 'image_array', xDim, yDim 是给定的。您会注意到一些已注释掉的其他尝试。

【问题讨论】:

    标签: c# image image-processing graphics edge-detection


    【解决方案1】:

    Sobel(和其他基于梯度的滤波器)受到噪声的影响。您可以使用高斯平滑对图片进行预过滤并比较结果。请注意,平方差的limit = 1000000 对应于大约 1000 的差异幅度 - 这对于 16 位 (MAX=65535) 图片来说是相当小的值。
    保存为 JPG 会使图片更加模糊 - 锐利边缘被涂抹,高频噪点被降低。所以玩一点点平滑和限制。

    【讨论】:

    • 我一直在摆弄这个。但后来我(头脑发热)突然意识到我所说的另一个软件,它让它看起来如此简单,就是将图像的大小更改为我所看到的画布大小——呃。所以不是处理 5700*3700 的图像,而是处理 550*780,我当然是四舍五入,但你得到了图片。所以是的,它正在平滑......我还没有完全完成这个,但最后,我正在接受我的教育。
    • 上面的代码完全不是我在用的了,但我正在做你说的:使用高斯平滑,而不是实际应用 Kirsh 边缘检测......谢谢
    猜你喜欢
    • 2020-10-11
    • 2020-04-06
    • 2016-11-07
    • 2012-12-30
    • 2015-08-09
    • 2018-05-17
    • 1970-01-01
    • 2016-10-03
    • 1970-01-01
    相关资源
    最近更新 更多