【问题标题】:Image Processing: The result of Sobel filter turns out to be gray instead of black and white?图像处理:Sobel 滤镜的结果原来是灰色而不是黑白?
【发布时间】:2019-03-25 14:33:10
【问题描述】:

我正在尝试自己实现一个 Sobel 过滤器。

我得到的结果和这个很像(灰色):

但不是这样(黑白渐变):

我曾尝试使用阈值,但感觉不对:

有没有什么方法可以把灰度变成黑白渐变结果?


以下是我在 C# 中过滤图像的步骤:

  1. 从文件转换位图(已经是灰度)
  2. 使用 Sobel 核对每个像素进行卷积(例如水平)

    私有静态浮点[][] Sobel3x3Kernel_Horizo​​ntal() { return new float[][] { new float[]{ 1, 2, 1}, new float[]{ 0, 0, 0 }, new float[]{ -1, -2, -1} }; }

  3. 重新映射所有值,让它们落在0~255的范围内(否则会出现负值或大于255的值,不能用来做Bitmap.SetPixel(int x, int y,颜色颜色)

  4. 输出位图结果(灰度)

【问题讨论】:

标签: c# image-processing sobel


【解决方案1】:

要复制您从 Wikipedia 链接的图片,请执行以下步骤:

  1. 用Sobel核计算卷积得到x导数dx

  2. 计算另一个卷积以获得y导数dy(转置内核)。

  3. 这两个导数一起形成梯度(每个像素的向量值)。通过计算sqrt(dx^2 + dy^2) 确定幅度。 ^2这里表示正方形。

  4. 如果您想要纯黑白结果,请设置阈值,否则通过将结果乘以某个值来缩放结果,以使显示的图像看起来不错。

请注意,您所说的 “灰度图像问题” 只是将 0 值映射到中间灰色(您的第 3rd 步骤),因此负可以显示值。这是显示导数的正确方法,否则负值将被剪裁,因此不可见。这些负值是导​​数的重要组成部分。但是这个映射应该用于显示,应该总是对原始值进行进一步的计算。

【讨论】:

  • 非常感谢您回答我的问题!所以在你的第三步之后我得到了幅度,我设置了一个 if-else 语句(不是针对 x 梯度也不是 y 梯度,而是针对幅度)if(magnitude > 255){magnitude = 255;} else if(magnitude < 0){magnitude = 0;} 丢弃负值和大于 255 的值,现在我终于有美妙的结果! drive.google.com/file/d/1lfhJp-ynuBmuh9XC55mJ_Ig_8fCEhy0O/view我希望我的 if-else 调节幅度范围的语句在这里是合适的。
  • 所以是我的第三步(重新映射)导致灰度图像问题......否则,就像你说的那样,梯度幅度图像本来应该是黑色的和白色。
  • 导数有负值,梯度幅度没有。您可以通过将梯度幅度图像乘以255/max 来缩放,其中max 是最大值。您也可以在执行过程中进行剪辑,但会在那里丢失信息。您所说的“灰度图像问题”只是将 0 值映射到中灰色,以便显示负值。这是完全有效的,但仅用于显示,应始终对原始值进行进一步计算,而不是缩放后的值。
  • 当我将您的结果与维基百科中的图像进行比较时,我得出的结论是您没有正确计算幅度。确保取两个分量的平方和,而不是直接取它们的总和。您应该看不到负值,并且砖块的所有 4 个边缘都应该具有相同的响应 - 在您的结果中,只有右侧和底部边缘有响应,其他两个可能有您设置为零的负响应。
  • 或者您可能正在丢弃dxdy 中的负值。不要那样做。将它们存储在有符号整数类型(或浮点类型)数组中
猜你喜欢
  • 2018-01-05
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
  • 2021-06-23
相关资源
最近更新 更多