OpenCV————图像阈值

阈值 就是将图像分割的界限。一幅图像包括目标物体(前景)、背景还有噪声,阈值法可将图像和背景分割开。有简单阈值,自适应阈值,Otsu’s 二值化等,学习到的函数有:

  • cv2.threshold 简单阈值
  • cv2.medianBlur 中值滤波
  • cv2.adaptiveThreshold 自适应阈值
  • cv2.GaussianBlur 高斯滤波

导入需要的包

import cv2
import numpy as np
import matplotlib.pyplot as plt

简单阈值

这种方法整张图都采用一个数做阈值,是全局阈值。
cv2.threshold(src, thresh, maxval, type),src灰度图;thresh阈值;maxval最大值;type阈值类型。其中,阈值类型有以下几种:

  • cv2.THRESH_BINARY:二值化操作,像素值大于阈值的点用maxval最大值表示,小于阈值用0表示。
  • cv2.THRESH_BINARY_INV:表示阈值的二值化翻转操作,大于阈值的使用0表示,小于阈值的使用最大值表示。
  • cv2.THRESH_TRUNC:截断操作,大于阈值的使用阈值表示,小于阈值的不变。
  • cv2.THRESH_TOZERO:化零操作,大于阈值的不变,小于阈值的使用0表示
  • cv2.THRESH_TOZERO_INV:化零操作的翻转,大于阈值的使用0表示,小于阈值的不变

函数有两个返回值,第一个为 retVal,第二个就是阈值化之后的结果图像了。

img=cv2.imread('test.jpg',0)#以灰度模式读入图像
#img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#将彩色图像转化为灰度图,两种方法都可以使用
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)#二值化操作,像素值大于127的点用225表示,小于阈值使用0表示
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)#表示阈值的二值化翻转操作,
                                                            # 大于阈值的使用0表示,小于阈值的使用最大值表示
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)#截断操作,大于阈值的使用阈值表示,小于阈值的不变。这里225起到了什么作用?
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)#化零操作,大于阈值的不变,小于阈值的使用0表示
ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)#化零操作的翻转,大于阈值的使用0表示,小于阈值的不变

titles=['img','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()

OpenCV————图像阈值_第1张图片

自适应阈值

当同一幅图像上的不同部分的具有不同亮度时,这种情况下我们需要采用自适应阈值。根据图像上的每一个小区域计算与其对应的阈值,因此在同一幅图像上的不同区域采用的是不同的阈值。
cv2.adaptiveThreshold(src, maxval, Adaptive Method, thresh_type,Block Size, C),函数的返回值只有一个阈值化的图像。

  • Adaptive Method:计算阈值的方法,包括:
    - cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
    - cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取自相邻区域的加权和,权重为一个高斯窗口
  • thresh_type:阈值类型
  • Block Size:邻域大小(用来计算阈值的区域大小)。
  • C:常数,阈值就等于平均值或者加权平均值减去这个常数。
img=cv2.imread('test.jpg'0)
img=cv2.medianBlur(img,5)#中值滤波,滤波模板的尺寸大小,必须是大于1的奇数
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)#二值化
thresh2=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)#阈值取自相邻区域的平均值
#参数的意义:灰度图,最大值,自适应计算阈值方法,阈值类型,邻域,常数:阈值就等于平均值或者加权平均值减去这个常数
thresh3=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)#阈值取自相邻区域的加权和
titles=['img','BINARY','MEAN','GAUSSIAN']
images=[img,thresh1,thresh2,thresh3]
for i in range(4):
    plt.subplot(2,2,i+1)
    plt.imshow(images[i],cmap='gray')#opencv和matplotlib颜色通道不一样,显示灰度图时,将cmap的值设置为'gray'。
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

OpenCV读取彩色图像的颜色通道是按B\G\R的顺序,而在matplotlib中是按R\G\B的顺序。如果要将opencv读取的彩色图像在matplotlib中显示,需要通过拆分、融合通道的方法将通道顺序改一下,如果是显示灰度图像,需要将imshow中cmap的默认值改成’gray’,否则就会出现下图的情况。

OpenCV————图像阈值_第2张图片

在图像处理中,在进行如边缘检测这样的进一步处理之前,通常需要首先进行一定程度的降噪。中值滤波是图像处理中的一个常用步骤,它对于斑点噪声(speckle noise)和椒盐噪声(salt-and-pepper noise)来说尤其有用。保存边缘的特性使它在不希望出现边缘模糊的场合也很有用。

OpenCV————图像阈值_第3张图片
加入中值滤波的结果,可以去除一些椒盐和斑点噪声,边缘更加明显。
OpenCV————图像阈值_第4张图片

Otsu’s二值化

在使用全局阈值时,我们只有通过不断地尝试来确定阈值,Otsu 二值化则可以自动计算来寻找最优的阈值。这里用到到的函数还是 cv2.threshold(),但是需要多传入一个参数:cv2.THRESH_OTSU。这时要把阈值设为 0。然后算法会找到最
优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal 值与设定的阈值相等。

img=cv2.imread('zs.jpg',0)
ret1,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret2,thresh2=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)#需要把阈值设为0,算法会找到最优阈值,返回给ret.
blur=cv2.GaussianBlur(img,(5,5),0)#高斯滤波做平滑处理去除噪声,(5,5)高斯核,标准差取0,
# 高斯矩阵的尺寸越大,标准差越大,处理过的图像模糊程度越大。
ret3,thresh3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
images = [img, 0, thresh1,img, 0, thresh2,blur, 0, thresh3] #这个0是直方图,为什么呢???
titles=['img','histogram','BINARY','img','histogram','THRESH_OTSU','blur','histogram','THRESH_OTSU']
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()

OpenCV————图像阈值_第5张图片

你可能感兴趣的:(opencv,opencv,python)