OpenCV 图像阈值转换,灰度图变为二值图

文章目录

    thresholding (阈值转换)

    名词,中文翻译为: 阈值转换法;阈值。

    image thresholding,这个词看起来比较抽象,但是结合使用场景,就非常好理解了。

    其用在, 将灰度图转换为二值图。

    • 二值图像是指仅仅包含黑色和白色两种颜色的图像。这种格式下,可以把一张图片理解为只包含 0 或 1 (255) 值的二维矩阵。
    • 灰度图 (grayscale image) 将灰度处理为256个灰度级。而不是简单的 0 或 255 两个值。

    而有了二值图,就可以方便的进行自动绘制轮廓。所以,图片阈值转换操作非常有价值。

    image thresholding 的三种方法

    • simple thresholding
    • adaptive thresholding
    • Otsu’s thresholding

    simple thresholding (简单阈值转换)

    这个方法简单粗暴。对于灰度图像的每个像素:

    • 大于阈值的,赋值成一个指定的值,通常是 255
    • 小于等于阈值的,赋值为 0

    对于的 opencv python 函数:

    threshold(src, thresh, maxval, type) ->	retval, dst
    

    参数说明:

    • src:原图。一般是灰度图
    • thresh: 阈值
    • maxval:目标值,例如 255
    • type: THRESH_BINARY, THRESH_BINARY_INV, THRESH_OTSU 等,其他参考下面的函数说明。

    详细参考 threshold 函数说明

    Otsu’s thresholding (大津阈值转换)

    也称为大津算法,大津二值化法,最大类间差法。由日本人大津 Otsu 于 1979 年提出,由此得名。

    对于图像识别功能来说,需要手动设置一个阈值其实是不够的,如果能自动确定这个阈值就完美了。
    opencv 内置了两个方法来自动选取阈值: Otsu’s 及 Triangle。

    至于原理,可以参考 大津算法

    算法假定该图像根据双模直方图(前景像素和背景像素)把包含两类像素,于是它要计算能将两类分开的最佳阈值,使得它们的类内方差最小;由于两两平方距离恒定,所以即它们的类间方差最大。

    我只领会了意思,但没有看懂实现。。。

    大津算法使用方法:

    ret, th = cv.threshold(img, 0, 255, cv.THRESH_OTSU)
    
    • 参数 thresh 可以为任意值,因为已经不起作用
    • 返回值 ret 为最终使用的阈值

    adaptive thresholding (自适应阈值转换)

    前面的 simple thresholding 和 otsu thresholding 都是在整个图像中使用固定的阈值进行二值化。
    但如果图片的不同区域光照条件差异巨大,这个方法就不合适了。所以出现了 adaptive thresholding。

    即,不同区域使用不同的阈值。

    adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C) ->	dst
    
    • adaptiveMethod decides how the threshold value is calculated: cv.ADAPTIVE_THRESH_MEAN_C 均值: The threshold value is the mean of the neighbourhood area minus the constant C. cv.ADAPTIVE_THRESH_GAUSSIAN_C 高斯: The threshold value is a gaussian-weighted sum of the neighbourhood values minus the constant C.
    • blockSize: Size of a pixel neighborhood that is used to calculate a threshold value for the pixel: 3, 5, 7, and so on. 必须为奇数?
    • C: Constant subtracted from the mean or weighted mean (see the details below). Normally, it is positive but may be zero or negative as well.
    • thresholdType: 只能设置成 THRESH_BINARY 或 THRESH_BINARY_INV。不能设置成大津算法。

    关键是确定 blockSize 和 C 的值。

    同一张图,adaptiveMethod 不同,效果差异巨大。例如:

    用 ADAPTIVE_THRESH_GAUSSIAN_C 处理的效果

    ADAPTIVE_THRESH_GAUSSIAN_C

    用 ADAPTIVE_THRESH_MEAN_C 处理的效果

    ADAPTIVE_THRESH_MEAN_C

    看起来,高斯处理的结果更像轮廓;而均值处理的效果更适合背景分离。

    • cv2.ADAPTIVE_THRESH_MEAN_C:邻域所有像素点的权重值是一致的。
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:与邻域各个像素点到中心点的距离有关,通过高斯方程得到各个点的权重值。参考下面的高斯加权。

    自适应阈值法,整个背景被判定为黑的原理

    一开始我没有想明白的是,这个阈值是怎么算出来的,那些背景的黑色区域是如何判定出来的?
    但是早上上班的路上,走路的时候突然想明白了。看来笨一点没关系,多琢磨琢磨就行了。

    使用均值法,假设局部区域 100个像素点,只要有一个是亮点,所有像素点的均值就是一个大于其他99个像素点的值。如此,二值化之后,就会变成黑黑的一片。

    非背景区域同理。

    如果效果不明显,调整常数 C 即可。

    高斯加权

    首先要知道什么是高斯分布(英语:Gaussian distribution),即正态分布(英语:Normal distribution),是一个非常常见的连续概率分布。正态分布的概率密度函数曲线呈钟形,因此人们又经常称之为钟形曲线。正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。

    正态分布概念是由法国数学家棣莫弗于1733年首次提出的,后由德国数学家Gauss率先将其应用于天文学研究,故正态分布又叫高斯分布。德国10马克的印有高斯头像的钞票,其上还印有正态分布的密度曲线。

    例如,用于高斯模糊。因为图像都是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更合理,距离越近的点权重越大,距离越远的点权重越小。计算平均值的时候,我们只需要将”中心点”作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。

    image histogram (图片直方图)

    以灰度图为例,我们用横轴代表 0-255 的灰度数值,竖轴代表照片中对应灰度的像素数量,这个函数图像就被称为直方图。
    可以借此直观地看到灰度的分布及比例。

    而大津算法就是基于直方图计算出来的。举一个极端的例子,一个只有两个灰度值的图片,其直方图只会有两个波峰。
    那么其阈值应该是介于两个波峰之间的一个值。

    延伸阅读,直方图在摄影中的应用

    效果体验

    做了一个在线版的 opencv 图像处理微信小程序,欢迎体验

    opencv 图像处理微信小程序

    参考

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式