计算机视觉技术 - 图像阈值

图像阈值

图像阈值(threshold),即图像的分割基准,基于此可完成图像的二值化。图像二值化可用于 OCR 成图像的分割(也是最为简单的一种)。这种分割是基于图像像素值级别的差异,且一般的对象是灰度图像。

图像阈值的进一步处理就是二值化,二值化包含但不限于“大于阈值为255,小于阈值为0”的处理模式。

threshold()

对于每个像素,应用相同的阈值。如果像素值小于阈值,则将其设置为0,否则将其设置为最大值。

  • 第一个参数是源图像,它应该是灰度图像。
  • 第二个参数是阈值,用于对像素值进行分类。
  • 第三个参数是分配给超过阈值的像素值的最大值。
  • OpenCV 提供了不同类型的阈值,这由函数的第四个参数给出。所有简单的阈值类型为:
    • cv.THRESH_BINARY
    • cv.THRESH_BINARY_INV
    • cv.THRESH_TRUNC
    • cv.THRESH_TOZERO
    • cv.THRESH_TOZERO_INV

本方法返回两个输出。第一个是使用的阈值,第二个输出是阈值后的图像。
以下代码比较了不同的简单阈值类型:

参考代码

import cv2 as cv
from matplotlib import pyplot as plt
#读取图像
img = cv.imread('../data/colorStone.jpg', cv.IMREAD_GRAYSCALE)
#不同二值化处理
ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)  #   表示阈值的二值化操作,大于阈值使用maxval表示,小于阈值使用0表示
ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV) #表示阈值的二值化翻转操作,大于阈值的使用0表示,小于阈值的使用最大值表示
ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC) #表示进行截断操作,大于阈值的使用阈值表示,小于阈值的不变
ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO) #表示进行化零操作,大于阈值的不变,小于阈值的使用0表示
ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV) #表示进行化零操作的翻转,大于阈值的使用0表示,小于阈值的不变
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
 plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
 plt.title(titles[i])
 plt.xticks([]),plt.yticks([])
plt.show()

在这里插入图片描述
图 1. 不同二值化阈值的比较

Otsu的二值化

在全局阈值化中,我们使用任意选择的值作为阈值。相反,Otsu 的方法避免了必须选择一个值并自动确定它的情况。考虑仅具有两个不同图像值的图像(双峰图像),其中直方图将仅包含两个峰。一个好的阈值应该在这两个值的中间。类似地,Otsu的方法从图像直方图中确定最佳全局阈值。为此,使用了 cv.threshold 作为附加标志传递。阈值可以任意选择。然后,算法找到最佳阈值,该阈值作为第一输出返回。
查看以下示例,输入图像为噪点图像。在第一种情况下,采用值为 127 的全局阈值。在第二种情况下,直接采用 Otsu 阈值法。在第三种情况下,首先使用 5x5 高斯核对图像进行滤波以去除噪声,然后应用Otsu阈值处理。了解噪声滤波如何改善结果。

参考代码

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('../data/colorStone.jpg', cv.IMREAD_GRAYSCALE)
# 全局阈值
ret1,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
# Otsu阈值
ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# 高斯滤波后再采用Otsu阈值
blur = cv.GaussianBlur(img,(5,5),0)
ret3,th3 = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
# 绘制所有图像及其直方图
images = [img, 0, th1,
 img, 0, th2,
 blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
 'Original Noisy Image','Histogram',"Otsu's Thresholding",
 'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]
plt.figure(figsize=(16,16))
for i in range(3):
 plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
 plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
 plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
 plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
 plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
 plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
图 2. 使用 Otsu 的二值化

参考资料

  • OpenCV API, https://docs.opencv.org/
  • matplotlib.pyplot.subplot, https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplot.html#matplotlib.pyplot.subplot
  • matplotlib.pyplot.imshow, https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html

猜你喜欢

转载自blog.csdn.net/m0_50614038/article/details/129494640