16位灰度图像的Sobel边缘检测输出

本文关键字:边缘检测 输出 Sobel 灰度图像 16位 | 更新日期: 2023-09-27 18:29:21

我在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是给定的。你会注意到一些人对其他尝试进行了评论。

16位灰度图像的Sobel边缘检测输出

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