OpenCV图像阈值处理之简单阈值和自适应阈值

OpenCV图像阈值处理之简单阈值和自适应阈值

  • OpenCV图像阈值处理
    • 简单阈值
      • 方法解释
      • 代码
    • 自适应阈值
      • 方法解释
      • 代码
    • 简单阈值和自适应阈值的异同点
  • 参考资料

OpenCV图像阈值处理

什么是阈值?简单说就是一个临界值(分界线)。

例如:一个班有50个学生,期末考试及格(60分及以上)的人数为40人,不及格的人数是10人。这里就是以60分为临界值划分的。60分,可以叫做一个阈值。

图像是由一个个的像素点构成的,像素点的值的范围是 [0, 255] 。对图像做阈值操作,就是给个临界值,筛选像素点。超过临界值,像素值置为几,低于临界值,像素值又置为几,根据不同的处理,就形成了不同的分类。

OpenCV图像阈值操作分为:简单阈值,自适应阈值。在实际应用中,自适应阈值用得比较多。

简单阈值

方法解释

简单阈值是整个图像采用同一个数作为阈值,是全局阈值

命令:cv2.threshold(src, thresh, maxval, type, dst=None)
返回两个值,第一个值是阈值,第二个值是阈值化处理后的图像。本文讲解仅使用第二个返回值。

  • 参数 src :输入图像,通常使用的是灰度图片
  • 参数 thresh :阈值
  • 参数 maxval :超过或低于阈值时,应该置为的值,也可以叫做最大值
  • 参数 type :通过阈值对图像处理的方法(超过或低于阈值的处理方式),有5种,分别是
    cv2.THRESH_BINARY 二值阈值化(超过阈值的像素值置为255,低于阈值的像素值置为0)
    cv2.THRESH_BINARY_INV 二值阈值化的反转(超过阈值的像素值置为0,低于阈值的像素值置为255)
    cv2.THRESH_TRUNC 截断阈值化(超过阈值的像素值置为阈值,低于阈值的像素值保持不变)
    cv2.THRESH_TOZERO 归零阈值化(超过阈值的像素值保持不变,低于阈值的像素值置为0)
    cv2.THRESH_TOZERO_INV 归零阈值化的反转(超过阈值的像素值置为0,低于阈值的像素值保持不变)

如果还是不太理解,可以参考 Opencv之图像固定阈值二值化处理threshold ,讲解很形象。 最重要的是 cv2.THRESH_TOZEROcv2.THRESH_TOZERO_INV 的操作没有讲反。我看了很多文章,都把这两种方法讲反了。

代码

import cv2
import matplotlib.pyplot as plt


original_image = cv2.imread("pic.jpg", cv2.IMREAD_GRAYSCALE)  # 以灰度模式打开图片

_, binary = cv2.threshold(original_image, 127, 255, cv2.THRESH_BINARY)  # 二值阈值化
_, binary_inv = cv2.threshold(original_image, 127, 255, cv2.THRESH_BINARY_INV)  # 二值阈值化的反转
_, trunc = cv2.threshold(original_image, 127, 255, cv2.THRESH_TRUNC)  # 截断阈值化
_, tozero = cv2.threshold(original_image, 127, 255, cv2.THRESH_TOZERO)   # 归零阈值化
_, tozero_inv = cv2.threshold(original_image, 127, 255, cv2.THRESH_TOZERO_INV)  # 归零阈值化的反转

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [original_image, binary, binary_inv, trunc, tozero, tozero_inv]
for i in range(6):
    plt.subplot(2, 3, i+1), plt.imshow(images[i], "gray")  # 以两行三列方式显示6张图片
    plt.title(titles[i])  # 设置图片标题
    plt.xticks([]), plt.yticks([])  # 取消坐标轴的刻度
# 显示图片
plt.show()

输出结果:
OpenCV图像阈值处理之简单阈值和自适应阈值_第1张图片

自适应阈值

方法解释

自适应阈值是局部阈值,同一个图像上的不同区域,使用不同的阈值。

命令:cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)

  • 参数 src :输入图像
  • 参数 maxValue :超过或低于阈值时,应该置为的值,也可以叫做最大值
  • 参数 adaptiveMethod :计算阈值的方法,有两种,分别是
    cv2.ADAPTIVE_THRESH_MEAN_C 阈值取自相邻区域的平均值
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C 阈值取自相邻区域的加权和,权重为一个高斯窗口
  • 参数 thresholdType :该参数与 cv2.threshold() 中的参数 type 用的方法是一样的,都是对图像阈值的处理方法
  • 参数 blockSize :邻域大小(用来计算阀值的区域大小),类似于CNN中的卷积核,值应该为奇数
  • 参数 C :一个常数(偏值),最终的阈值是adaptiveMethod计算出的阈值再减去该常数,一般情况下置为0

代码

import cv2
import matplotlib.pyplot as plt


original_image = cv2.imread("chessboard.jpg", cv2.IMREAD_GRAYSCALE)  # 以灰度模式打开图片

_, binary = cv2.threshold(original_image, 127, 255, cv2.THRESH_BINARY)  # 二值阈值化
# 阈值取自相邻区域的平均值
thresh_mean = cv2.adaptiveThreshold(original_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 17, 0)
# 阈值取自相邻区域的加权和,权重为一个高斯窗口
thresh_gaussian = cv2.adaptiveThreshold(original_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 17, 0)

images = [original_image, binary, thresh_mean, thresh_gaussian]
titles = ['Original Image', 'BINARY', 'MEAN', 'GAUSSIAN']

for i in range(4):
    plt.subplot(2, 2, i+1), plt.imshow(images[i], "gray")
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])  # 取消坐标轴的刻度
plt.show()

输出结果:
OpenCV图像阈值处理之简单阈值和自适应阈值_第2张图片

简单阈值和自适应阈值的异同点

  • 相同点
  1. 需要给定最大值,使得像素值超过或低于阈值时,应该把值设为多少,做个参考。
  2. 通过阈值对图像处理的方法,都是一样的,有:
    cv2.THRESH_BINARY
    cv2.THRESH_BINARY_INV
    cv2.THRESH_TRUNC
    cv2.THRESH_TOZERO
    cv2.THRESH_TOZERO_INV
  • 不同点
  1. 阈值适用范围
    简单阈值处理,给定的阈值,用于整个图像,是全局阈值。
    自适应阈值处理,计算出的阈值,只用于图像的局部区域,不同区域的阈值不同,所以是局部阈值。

  2. 阈值设定
    简单阈值处理,是直接给定一个阈值(很直接)。
    自适应阈值处理,所需的阈值,是通过 cv2.ADAPTIVE_THRESH_MEAN_Ccv2.ADAPTIVE_THRESH_GAUSSIAN_C 方法计算出来的。

  3. 偏值
    简单阈值处理,由于是直接给定的阈值,所以没有在该阈值的基础上,再作调整。
    自适应阈值处理,在通过电脑计算出局部阈值之后,可以给定一个常数(偏值)再进行调整。

参考资料

[1] Aollo小北.OpenCV-Python中文教程
[2] 啧啧啧biubiu.Opencv之图像固定阈值二值化处理threshold
[3] bingma.OpenCV-图像阈值-简单阈值、自适应阈值、Otsu’s 二值化

你可能感兴趣的:(OpenCV,opencv,机器学习)