【问题标题】:How to get threshold value from histogram?如何从直方图中获取阈值?
【发布时间】:2012-07-01 05:49:33
【问题描述】:

我正在 OpenCV 中编写一个 Android 应用程序来检测 blob。一项任务是对图像进行阈值化,以区分前景对象和背景(见图)。

只要图像是已知的,它就可以正常工作,并且我可以手动将阈值传递给 threshold()——在这个特定的图像中,比如说 200。但是假设图像不知道,唯一的知识是是深色实心背景和浅色前景对象如何动态计算阈值?

我遇到了可以计算灰度图像强度分布的直方图。但我找不到分析直方图并选择感兴趣对象(较轻)所在的值的方法。那是;我想将明显较暗的背景尖峰与较浅的前景尖峰区分开来——在这种情况下高于 200,但在另一种情况下,如果对象是灰色的,则可以说是 100。

【问题讨论】:

  • 有很多方法可以做到这一点。也许大津的方法可能对你有用。如果不是,恕我直言,它仍然是一个很好的起点。 en.wikipedia.org/wiki/Otsu%27s_Method
  • 你能上传100阈值的图片吗?因为在图像上高于 50 的阈值也是可以接受的...

标签: image-processing opencv computer-vision


【解决方案1】:

如果你说背景很暗(黑色)而前景很亮,那么我建议使用YUV color space(或任何其他YXX,如YCrCb等),因为此类色彩空间的第一个组成部分是亮度(或lightning)。

所以在Y通道被提取出来之后(通过extractChennel函数)我们需要分析这个通道的直方图(图片):

看到第一个(左)驼峰了吗?它代表图像上的黑暗区域(您的情况下的背景)。所以我们现在的目标是找到一个包含这个驼峰的段(在横坐标上,它是图像中的红色部分)。显然这个段的左边点是。正确的点是第一个点:

  • 直方图的(局部)最大值从点的左边算起
  • 直方图的值小于一些小的epsilon(可以设置为10)

我画了一条绿色的垂直线来显示该直方图中段的右点的位置。

就是这样!该段的正确点是所需的阈值。结果如下(epsilon 为 10,计算出的 threshold 为 50):

我认为删除上图中的噪点对你来说不是问题。

【讨论】:

    【解决方案2】:

    如果你所有的图片都是这样,或者可以带成这样的风格,我认为cv2.THRESHOLD_OTSU,即otsu的阈值算法是一个不错的选择。

    以下是在命令终端中使用 Python 的示例:

    >>> import cv2
    >>> import numpy as np
    >>> img2 = cv2.imread('D:\Abid_Rahman_K\work_space\sofeggs.jpg',0)
    
    >>> ret,thresh = cv2.threshold(img2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    
    >>> ret
    122.0
    

    ret 是自动计算的阈值。我们只是将“0”作为阈值传递。

    我在 GIMP 中获得了 124 分(与我们获得的结果相当)。它还消除了噪音。见下面的结果:

    【讨论】:

      【解决方案3】:

      以下是 Abid 答案的 C++ 实现,适用于 OpenCV 3.x:

      // Convert the source image to a 1 channel grayscale:
      Mat gray;
      cvtColor(src, gray, CV_BGR2GRAY);
      // Apply the threshold function with the CV_THRESH_OTSU setting as well
      // You can skip having it return the value, but I include it for showing the
      // results from OTSU
      double thresholdValue = threshold(gray, gray, 0, 255, CV_THRESH_BINARY+CV_THRESH_OTSU);
      // Present the threshold value
      printf("Threshold value: %f\n", thresholdValue);
      

      对原始图像运行它,我得到以下信息:

      OpenCV 为其计算了 122 的阈值,接近 Abid 在他的答案中找到的值。

      为了验证,我更改了原始图像,如下所示:

      并生成以下内容,新阈值为 178:

      【讨论】:

        猜你喜欢
        • 2014-08-08
        • 2014-05-03
        • 2016-06-20
        • 2017-01-18
        • 2014-01-01
        • 2019-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多