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

更新日期: 2022-04-12 阅读次数: 6876 字数: 1378 分类: 图像识别

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 图像处理微信小程序

参考

tags: OpenCV 大津算法

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式