如何从直方图中获取阈值?

Tru*_*Tru 12 opencv image-processing computer-vision

我正在OpenCV中编写一个Android应用来检测blob.一个任务是阈值图像以区分前景对象和背景(见图像).

只要图像已知并且我可以手动将阈值传递给阈值(),它就能正常工作 - 在这个特定的图像中,例如200.但是假设图像不知道只知道会有一个黑暗固体背景和较轻的前景对象如何动态计算出阈值?

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

在此输入图像描述

Abi*_*n K 10

如果您的所有图像都是这样的,或者可以使用这种风格,我认为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
Run Code Online (Sandbox Code Playgroud)

ret是自动计算的阈值.我们只是将"0"作为阈值传递给它.

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

在此输入图像描述


Art*_*huk 7

如果你说的背景是黑色(黑)和前景较轻,那么我建议使用YUV色彩空间(或任何其他YXX喜欢的YCrCb等),因为这样的色彩空间的第一部分是亮度(或闪电).

光通道

因此,在提取Y通道(通过extractChennel函数)后,我们需要分析该通道的直方图(图像):

直方图

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

  • 直方图的(局部)最大值来自该点的左侧
  • 直方图的值小于某个小的epsilon(你可以设置为10)

我绘制了一条绿色垂直线,以显示此直方图中段的正确位置.

就是这样!该段的右侧点是所需的阈值.这是结果(epsilon为10,计算出的值为50):

结果

我认为删除上图中的噪音不是问题.