图像阈值处理

释放双眼,带上耳机,听听看~!
本文介绍了图像阈值处理的基本概念和在OpenCV中的实现方法,以及常用的阈值处理方法,包括简单阈值处理。

1.图像阈值处理

在图像处理中,阈值处理是一种常用的技术,可以将图像转换为二值图像,即只有两个像素值(一般为黑色和白色)。OpenCV提供了多种图像阈值处理的方法,接下来我们讨论一下在opencv如何对一个图形进行阈值处理。

1.1简单阈值处理(Simple Thresholding)

简单阈值处理是一种基本的阈值处理方法,它将图像的每个像素与一个阈值进行比较,并根据比较结果将像素设置为两个值中的一个。在OpenCV中,调用cv2.threshold()来实现,主要包含4个参数: 第一个为输入图,第二个我们设定的阈值,一般为127,那么我们就以127为界进行判断,第三个参数是最大的一个可能值,一般情况下为255。主要就是第四个参数,表示我们要进行的阈值处理及判断条件。这里主要包含5种方法,具体如下

cv2.threshold(input, thresh, maxval, type)

  • input: 输入图,只能输入单通道图像,通常来说为灰度图
  • thresh: 阈值
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • type:二值化操作的类型,包含以下5种类型:
  • cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
    • cv2.THRESH_BINARY_INV THRESH_BINARY的相反操作
    • cv2.THRESH_TRUNC 大于阈值部分设为阈值,其余不变
    • cv2.THRESH_TOZERO 大于阈值部分不变,否则设为0
    • cv2.THRESH_TOZERO_INV THRESH_TOZERO的相反操作

通常情况下,在我们图像当中,越亮的地方值越大,以第一个为例,在这里越亮的地方,超过阈值部分,我取255,是不是相当于把它放到极亮,相当于就是一个白点。否则的话就取零,因此比较暗的地方,小于阈值时我们就直接给它取零,相当于是一个黑的地方。接下来我们来看看这几种阈值处理的效果

首先导入一张灰度图

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline 
 
img=cv2.imread('yangqi.jpg') #导入你要读取的图片路径
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #灰度图读取
img_gray.shape
(238, 218)

可以看到此时的通道数为1

# 其中ret返回的是阈值
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) #超过127的取值为255,否则为0
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)#超过127的取值为0,否则为255
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)#超过阈值的设为阈值,否则不变
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)#超过127的不变,否则为0
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)#超过127的为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()

图像阈值处理

第一幅图:原始的图像就是这只小狗,可以看出身体比较白,其余地方比较暗。

第二幅图:使用BINARY二值法处理的结果,处理完之后大于127亮点的全为白,暗点的全为黑,这个意思这是咱们第一种方法。

第三幅图: 使用BINARYINV处理的结果,这和我们第二幅图的结果完全相反,处理完之后大于127亮点的全为黑,暗点的全为白

第四幅图: 使用TRUNC截断值处理的结果,这个比较好理解,所有大于127截断使其等于127了,其余的不变

第五幅图:使用TOZERO,从名字上就可以理解它的用法,大于阈值的部分保持不变,小于阈值的部分变为0

第六幅图:使用TOZERO_INV,和上一种方法的结果刚好相反,大于阈值的变为0,小于阈值的保持不变。

1.2自适应阈值处理(Adaptive Thresholding)

自适应阈值处理是一种根据图像局部区域的特性自动确定阈值的方法。它将图像分成若干个小区域,并根据每个区域内像素的统计信息来计算阈值。在OpenCV中,可以使用cv2.adaptiveThreshold()函数来实现自适应阈值处理,具体语法如下

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

参数说明:

  • src:输入的灰度图像,单通道图像。
  • maxValue:当像素超过阈值时,所设置的最大像素值。
  • adaptiveMethod:自适应方法的类型。可以是以下两种之一:
    • cv2.ADAPTIVE_THRESH_MEAN_C:根据邻域块的均值计算阈值。
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:根据邻域块的加权和的高斯平均值计算阈值。
  • thresholdType:阈值处理的类型。可以是以下两种之一:
    • cv2.THRESH_BINARY:超过阈值的像素被设置为 maxValue,否则设置为0。
    • cv2.THRESH_BINARY_INV:超过阈值的像素被设置为0,否则设置为 maxValue
  • blockSize:用于计算阈值的像素邻域大小。它必须是奇数,并且大于1。
  • C:在计算阈值时的常数,用于对均值或加权和进行调整。

函数的返回值是处理后的二值图像。

thresh1 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,3) #这里领域大小为3
thresh2 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,3,3)#这里领域大小为3

titles = ['Original Image', 'BINARY', 'BINARY_INV']
images = [img_gray, thresh1, thresh2]

for i in range(3):
    plt.subplot(1,3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

图像阈值处理

通过自适应阈值处理,我们可以根据每个像素邻域内的统计信息来确定阈值,从而更好地适应不同区域之间的光照变化。这对于处理具有不均匀光照条件的图像非常有用,例如图像中存在阴影或光源不均匀的情况。

1.3Otsu’s阈值处理

Otsu's阈值处理是一种自动确定阈值的方法,它能够找到一个最佳的阈值,使得将图像分割为两个类别后的类别间方差最小化, 这种方法对于没有先验知识的图像分割非常有用。在OpenCV中,我们调用cv2.threshold()函数,并将阈值类型设置为cv2.THRESH_OTSU来实现Otsu's阈值处理。

ret, thresh = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

titles = ['Original Image', "Otsu's"]
images = [img_gray, thresh]

for i in range(2):
    plt.subplot(1,2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

ret 是计算得到的最佳阈值,thresh 是通过应用 Otsu's 方法得到的二值图像。

图像阈值处理

ret
119.0

可以看到,Otsu's方法会自动计算阈值,这里阈值等于119,并将图像分为两个类别(黑色和白色)。

使用 Otsu's 阈值处理,我们无需手动选择阈值,而是通过计算来确定最佳阈值,从而实现更准确的图像分割。这对于具有不同光照条件、对比度变化或噪声存在的图像尤其有用。

2.平滑处理

当我们处理图像时,有时候需要对图像进行平滑处理,以减少噪声、去除细节或者模糊图像,它的具体计算有点类似卷积的计算,在介绍具体方法之前我们先来看一张图片:

img = cv2.imread('lenaNoise.png')
cv2.imshow('Noise', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像阈值处理

可以看到这张图片上面有很多椒盐噪声,我们希望能够用平滑方法来处理,在OpenCV提供了多种图形平滑处理方法,下面我们详细介绍一些常用的方法:

2.1均值滤波(Mean Filter)

将每个像素的邻域像素的平均值作为该像素的新值。这种滤波器对于去除轻度噪声非常有效,但可能会导致图像变得模糊。在OpenCV中,我们调用cv2.blur()函数来实现均值滤波。

blur = cv2.blur(img, (3, 3)) #使用3×3的滤波器
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像阈值处理
可以看见上面的椒盐噪声减弱了一些,没有那么明显,下面我们来看一下它的具体计算逻辑,这里我们选择了3×3的滤波器,因此,每次我们都会看以目标像素为中心的3×3的领域9个值,如下图所示,以204为中心,我们计算包括它在内及其领域共9个值的平均值来做代替。

图像阈值处理

2.2高斯滤波(Gaussian Filter)

刚刚我们介绍的均值平衡是简单的求算数平均,而高斯平衡认为其邻域像素的权重不应该一样,越靠近中心的像素权重应该越重,且权重服从高斯分布,然后使用高斯权重来计算邻域像素的加权平均值。相比于均值滤波器,高斯滤波器能够更好地保留图像的细节信息。在OpenCV中,可以使用cv2.GaussianBlur()函数来实现高斯滤波。

# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
gaussian = cv2.GaussianBlur(img, (3,3), 1)  

cv2.imshow('gaussian', gaussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像阈值处理

2.3中值滤波(Median Filter)

中值滤波是一种非线性滤波器,它将每个像素的邻域像素的中值作为该像素的新值。这种滤波器对于去除椒盐噪声非常有效,同时能够保留图像边缘的细节,对于我们给出的这张图而言,效果非常好。在OpenCV中,我们调用cv2.medianBlur()函数来实现中值滤波。

# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 3)  # 中值滤波

cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像阈值处理

可以看出使用中值平滑处理后的效果针对于椒盐噪声非常好。下面我们将三个图放一起来比较

# 展示所有的
res = np.hstack((blur,gaussian,median))#按水平方向堆砌,三张图水平方向放一起

cv2.imshow('blur vs gaussian vs median', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像阈值处理

上述几种方法究竟选哪一个好呢?一般我们需要根据特定的任务和图像特征进行评估和调整,根据我们的需求和图像特点,选择合适的方法来实现图像的平滑处理,例如以本案例来说,使用中值平滑处理的效果是最好的。

本网站的内容主要来自互联网上的各种资源,仅供参考和信息分享之用,不代表本网站拥有相关版权或知识产权。如您认为内容侵犯您的权益,请联系我们,我们将尽快采取行动,包括删除或更正。
AI教程

2023年AI工具推荐,提升生产效率

2023-11-23 16:33:14

AI教程

CodeWhisperer: 亚马逊云科技新推出的AI代码生成工具

2023-11-23 16:35:14

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索