【问题标题】:How to detect anomalies in opencv (c++) if threshold is not good enought?如果阈值不够好,如何检测 opencv (c++) 中的异常?
【发布时间】:2017-07-17 18:17:17
【问题描述】:

我有这样的灰度图像:

我想检测这种图像的异常情况。在第一张图像(左上)我想检测三个点,在第二张(右上)有一个小点和一个“雾区”(在右下),最后一个,有也是图像中间某处的一个小点。

正常的静态阈值对我来说不起作用,而且 Otsu 的方法始终是最佳选择。有没有更好、更强大或更智能的方法来检测这样的异常?在 Matlab 中,我使用了类似 Frangi 过滤(特征值过滤)的东西。任何人都可以提出好的处理算法来解决这样的表面上的异常检测吗?

编辑:添加了另一个带有异常标记的图像:

使用@Tapio 的顶帽过滤和对比度调整。 由于@Tapio 为我们提供了如何增加表面异常对比度的好主意,就像我在开始时询问的那样,我向大家提供了我的一些结果。我有这样的图像:

这是我如何使用顶帽过滤和对比度调整的代码:

kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3), Point(0, 0));
morphologyEx(inputImage, imgFiltered, MORPH_TOPHAT, kernel, Point(0, 0), 3);  
imgAdjusted = imgFiltered * 7.2;

结果在这里:

还有一个问题是如何从最后一张图像中分割出异常??因此,如果有人知道如何解决它,那就接受吧! :) ??

【问题讨论】:

  • 计算灰度图像的平均值。高于平均值某个百分比的像素可以声明为异常值
  • @JeruLuke:这是一个“模式识别简介”级别的答案,但对 Otsu 方法和特征值过滤的引用告诉我,我们没有考虑这个。
  • 您能否提供更多关于我应该关注的 whitch 技术以及如何进行模式识别的信息?我应该在这里考虑一些“机器学习”的东西吗?
  • @skoda23:你当然可以在这个问题上扔一个 CNN,并提供足够的数据。它有效率吗?不完全是。你需要大量的训练数据吗?是的,至少与直接编程相比。是微不足道的吗?不,编写一个有用的错误函数需要做很多工作。

标签: c++ opencv image-processing anomaly-detection


【解决方案1】:

@skoda23,我会尝试使用微调参数对模糊部分进行锐化掩蔽,以便强调高频并对其进行彻底测试,以免在此过程中丢失任何重要信息。请记住,期望计算机完成超人类的工作通常不是一个好主意。如果人类对异常在哪里有疑问,计算机将不得不这样做。因此,首先对图像进行预处理很重要,这样异常对于人眼来说是显而易见的。非锐化掩蔽(或添加)的替代方案可能是 CLAHE。但同样:记住要非常小心地对其进行微调 - 它可能会过多地突出电路板的纹理并干扰您的任务。

基本阈值或 Otsu 的替代方法是 AdaptiveThreshold(),这可能是一个好主意,因为您要查找的不同区域之间的强度值存在差异。

我的第二个猜测是首先对最暗的点使用固定值阈值,然后尝试 Sobel 或 Canny。应该存在一个最佳邻域,其中电路板的纹理不会那么亮,并且异常会。您也可以在边缘检测之前尝试模糊(如果您已经通过阈值检测到了小缺陷)。

再次重申:对于此方法的每一步都进行大量实验对于任务而言至关重要,因为微调参数对于最终成功至关重要。我建议与the trackbar 交朋友,以加快进程。祝你好运!

【讨论】:

  • 我同意所有的说法。但是我仍然找不到带有轨迹栏的正确参数。我正在尝试解决像@MSalters 所说的真实世界是“模拟”的问题。我在帖子中添加了一张额外的图片。请快速浏览一下。你能推荐我吗,这里最好的过滤应该是什么。我目前正在尝试自适应阈值,但不能很好地调整它:/
  • @skoda23 如果您向我们提供显示您想要检测哪些异常以及哪些是正常的并且应该省略的图像,这将对每个人都有帮助
  • 您之前添加的 3 张图像上可见的纹理怎么样?为什么新图像上没有纹理?
  • 没有纹理也很简单。只需计算平均值和等于平均值​​某个百分比的基本阈值就足够了,因为板的强度在最后一张图片上非常一致。
  • 是的。检测板子。计算平均值并以此为基础设置阈值。假设平均值为 130,您的阈值将增加 30%,即 170(实际上是另一个实验发现的值)。阈值等于 170,我的意思是 cv2.threshold(img, 170, 255, 0)。但既然@Tapio 得到了很好的结果,你绝对应该尝试实现他的想法。
【解决方案2】:

您基本上是在处理现实是模拟的不幸事实。阈值是一种将模拟范围转换为离散(二进制)范围的方法。 任何阈值都可以做到这一点。那么“足够好”的阈值到底是什么意思?

让我们暂时搁置这个想法。我看到了很多异常——有点像灰色的蠕虫。显然,你忽略了它们。我应用的阈值与你不同。这可能是合理的,但您正在应用我没有的领域知识。

我怀疑这些灰色蠕虫会抛弃您的固定值阈值。这并不是说固定阈值的想法不好。您可以使用它来查找 一些 工件并排除它们。会遗漏一些较暗的斑块,但可以通过将每个像素替换为其邻域的中值,使用比这些蠕虫的宽度更大的邻域大小来消除。在黑暗的补丁中,这几乎没有作用,但它会消除小的局部变化。

我不会假装这两种异常是仅有的两种,但这确实是一个应用领域的问题,而不是关于技术的问题。例如。至少在这 3 个样本中,您似乎没有光照伪影(反射)。

【讨论】:

    【解决方案3】:

    您应该看看底帽过滤。它被定义为原始图像的差异和图像的形态闭合,它使小细节,例如你正在寻找的那些。

    我调整了对比度以使两个图像都可见。从强度上看,异常更加明显,并且更容易分割出来。

    我们来看第一张图:

    由于我使用的可视化工具造成的缩放,直方图值不代表现实。然而,相对距离确实如此。所以现在阈值范围更大了,目标从窗户变成了谷仓门。

    全局阈值(强度 > 15):

    Otsu 的方法在这里效果不佳。它将所有的小细节都分割到了前景。

    通过形态开放去除噪声后:

    我还假设黑点是您感兴趣的异常。通过将阈值设置得较低,您可以包含更多的表面细节。例如第三张图片在我看来没有任何特别有趣的特征,但那是你判断的。就像 m3h0w 所说的那样,如果某件事对你的眼睛来说很难判断,那么它可能对计算机来说是不可能的,这是一个很好的启发式方法。

    【讨论】:

    • 那是你@Tapio 的一些出色工作。你能给我一些 C++ 代码你是如何解决第一张图像的顶帽过滤和对比度调整的?我尝试了 tophat 过滤,它工作正常,但我看不到你做的那么好的结果。
    • @Tapio 做得很好。带有阈值的直方图可视化覆盖了您创建的东西还是某种原型工具?
    • @Tapio 我添加了我的一个结果,因为你建议使用 tophat 和adjustement。您能否向我们提供您对该结果的评论,并就如何改进这些结果给我们一些额外的建议?
    猜你喜欢
    • 2021-07-22
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2013-09-19
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    相关资源
    最近更新 更多