【问题标题】:Threshold to amplify black lines放大黑线的阈值
【发布时间】:2013-06-13 14:14:03
【问题描述】:

给定一张图像(如下图所示),我需要将其转换为二值图像(仅限黑白像素)。这听起来很简单,我尝试了两个阈值函数。问题是我无法使用这些功能中的任何一个获得完美的边缘。任何帮助将不胜感激。

我尝试过的过滤器是 RGB 和 HSV 空间中的欧几里得距离。

示例图片:

这是在运行 RGB 阈值过滤器之后。 (40% 之后的人工制品更多)

这是在运行 HSV 阈值过滤器之后。 (在 30% 时,路径变得几乎看不到,但由于噪音明显无法使用)

我使用的代码非常简单。将输入图像更改为适当的颜色空间,并用黑色检查欧几里得距离。

sqrt(R*R + G*G + B*B)

因为我是和黑色比较 (0, 0, 0)

【问题讨论】:

  • 你试过霍夫函数和噪声滤波器吗?我相信你可以很好地利用matlab的imnoise(..)
  • 不是真的,因为当我增加阈值时,很多图像会因为我猜的阴影而完全变黑。而且我认为噪声过滤器无法消除这些......我可能是错的。
  • 尝试使用边缘检测或使用霍夫变换之类的方法找到线条。
  • 我在android平台上写这个。所以,如果你们能推荐一个好的库来使用..我显然不想手工编写所有这些算法

标签: image-processing colors


【解决方案1】:

您的问题似乎是扫描图像上的照明变化,这表明局部自适应阈值方法会给您带来更好的结果。

Sauvola 方法根据原始图像窗口中像素的均值和标准差计算二值化像素的值。这意味着,如果图像的某个区域通常更暗(或更亮),则会针对该区域调整阈值,并且(可能)在二值化图像中减少暗斑或褪色线条。

http://www.mediateam.oulu.fi/publications/pdf/24.p

我还发现了 Shafait 等人的方法。以更高的时间效率实现 Sauvola 方法。缺点是您必须计算原始图像的两张完整图像,一张为每像素 8 位,另一张可能为每像素 64 位,这可能会出现内存限制问题。

http://www.dfki.uni-kl.de/~shafait/papers/Shafait-efficient-binarization-SPIE08.pdf

我没有尝试过这两种方法,但它们看起来很有希望。我通过粗略的 Google 搜索找到了两者的 Java 实现。

【讨论】:

    【解决方案2】:

    在 HSV 颜色空间中的 V 通道上运行自适应阈值应该会产生出色的结果。最好的结果来自大于 11x11 大小的窗口,不要忘记为阈值选择一个值。

    自适应阈值基本上是:

    if (Pixel value + constant > Average pixel value in the window around the pixel )
        Pixel_Binary = 1;
    else
        Pixel_Binary = 0;
    

    【讨论】:

    • 如果您已经开始使用大部分为灰色的图像,则无需转换为 HSV - 只需从 R、G、B 中选择噪声最少的通道,通常为绿色。
    【解决方案3】:

    由于噪声和光照变化,您可能需要自适应局部阈值,这也感谢 Beaker 的回答。

    因此,我尝试了以下步骤:

    • 将其转换为灰度。

    • 进行均值或中值局部阈值处理,我使用 10 作为窗口大小,使用 10 作为截距常数,得到了这个图像(较小的值也可能有效):

      如果您需要更多,请参考:http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm 有关此技术的信息。

    • 为确保阈值处理工作正常,我对其进行了骨架化以查看是否存在换行符。此骨架可能是进一步处理所需的骨架。

    • 要消除剩余的噪声,您只需在骨架化图像中找到最长的连接组件即可。

    谢谢。

    【讨论】:

      【解决方案4】:

      您可能希望将此作为一个三步操作。

      1. 使用调平,而不仅仅是阈值:获取输入并使用仅使中间色调变暗的参数缩放强度(伽马校正),而不去除暗部或亮部(例如,您的 rgb 阈值太强. 你丢失了一些台词)。

      2. 使用小内核卷积对生成的图像进行边缘检测(二进制图像的 5x5 应该绰绰有余)。使用简单的 [1 2 3 2 1 ; 2 3 4 3 2 ; 3 4 5 4 3 ; 2 3 4 3 2 ; 1 2 3 2 1] 内核(标准化)

      3. 对结果图像设置阈值。你现在应该有一个更好的二值图像了。

      【讨论】:

      • 我是在 Android 平台上写这篇文章的,所以你能指点我一个可以为我处理这些操作的好库吗?
      • 您指定的内核会模糊图像,而不是检测边缘。
      • 哎呀,抱歉,@Zaphod 说的很对:那是一个平滑内核;有简单的 5x5 内核,但en.wikipedia.org/wiki/Edge_detection 很好地说明了为什么它有效,以及一些常见的内核。另外:我不确定 Android 是否有任何内置功能,但作为一种基于 Java 的语言,如果您可以访问图像的像素,那么编写卷积非常简单。创建一个与图像像素数组大小相同的数组,对图像进行卷积,将结果放入新数组中,然后根据新数组进行阈值处理。
      【解决方案5】:

      你可以试试黑色的top-hat transform。这涉及从图像的关闭中减去图像。我使用了 11 的结构元素窗口大小和 0.1 的恒定阈值(25.5 表示 255 比例)

      你应该得到类似的东西:

      然后您可以轻松阈值:

      祝你好运。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-14
        • 2014-05-09
        • 2020-11-12
        • 2018-12-22
        • 2019-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多