第十四节,OpenCV学习(三)图像的阈值分割
图像的阈值处理
图像的阈值分割:图像的二值化(Binarization)
阈值分割法的特点是:适用于目标与背景灰度有较强对比的情况,重要的是背景或物体的灰度比较单一,而且总可以得到封闭且连通区域的边界。
一、简单阈值
选取一个全局阈值,然后把图像分成非黑即白的二值图像。
cv2.threshold()【源图像矩阵,进行分类的阈值,高于(低于)阈值时赋予的新值,方法选择参数】
返回两个值:阈值,阈值处理后的图像矩阵。
- cv2.THRESH_BINARY(黑白二值)
- cv2.THRESH_BINARY_INV(黑白二值翻转)
- cv2.THRESH_TRUNC(得到图像为多像素值)
- cv2.THRESH_TOZERO(当像素高于阈值时像素设置为自己提供的像素值,低于阈值时不作处理)
- cv2.THRESH_TOZERO_INV(当像素低于阈值时设置为自己提供的像素值,高于阈值时不作处理)
import cv2 import numpy as np img = cv2.imread('dog.jpg', 0)# 灰度图 # 黑白二值 res, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 黑白二值翻转 res, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) # 得到图像为多像素值 res, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC) # 当像素高于阈值时像素设置为255,低于阈值时不作处理 res, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO) # 当像素低于阈值时设置为255,高于阈值时不作处理 res, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV) print(res) cv2.imshow('thresh1', thresh1) cv2.imshow('thresh2', thresh2) cv2.imshow('thresh3', thresh3) cv2.imshow('thresh4', thresh4) cv2.imshow('thresh5', thresh5) cv2.imshow('gray-img', img) cv2.waitKey(0) cv2.destroyAllWindows()
二、自适应阈值
简单阈值是一种全局性的阈值,只需要设定一个阈值,整个图像都和这个阈值比较,而自适应阈值可以看成一种局部性的阈值,通过设定一个区域大小,比较这个点与区域大小里面像素点的平均值的大小关系确定这个像素点的情况。
这种方法理论上得到的效果更好,相当于在动态自适应调整属于自己像素点的阈值,而不是整幅图像都用一个阈值。
import cv2 import numpy as np img = cv2.imread('dog.jpg',0) res, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 第一个参数为原始图像矩阵 # 第二个参数为像素值上限 # 第三个是自适应方法: # cv2.ADAPTIVE_THRESH_MEAN_C:领域内均值 # -----cv2.ADAPTIVE_THRESH_GAUSSIAN_C:领域内像素点加权和,权重为一个高斯窗口 # 第四个值得赋值方法:只有cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV # 第五个Block size:设定领域大小(一个正方形的领域) # 第六个参数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值,就是求得领域内均值或者加权值) th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 2) th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) th4 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) cv2.imshow('img', img) cv2.imshow('th1', th1) cv2.imshow('th2', th2) cv2.imshow('th3', th3) cv2.imshow('th4', th4) cv2.waitKey(0) cv2.destroyAllWindows()
三、Otsu's二值化
cv2.threshold( )函数有两个返回值,一个是阈值,第二个是处理后的图像矩阵。
前面对于阈值的设定上,我们选择的阈值都是127,在实际情况中,有的图像阈值不是127得到的图像效果更好。那么这里就需要算法自己去寻找一个阈值,而Otsu's就可以自己找到一个认为最好的阈值。并且Otsu's非常适合于图像灰度直方图(只有灰度图像才有)具有双峰的情况。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('dog.jpg', 0) ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 简单滤波 ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU) # Otsu滤波 print(ret2) cv2.imshow('img', img) cv2.imshow('th1', th1) cv2.imshow('th2', th2) # 解决matplotlib中显示图像的中文乱码问题 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.hist(img.ravel(), 256) plt.title('灰度直方图') plt.show() cv2.waitKey(0) cv2.destroyAllWindows()