文章目录
1.图像二值化
图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出黑白效果的过程。
图像的二值化,在图像处理中是十分重要的一个步骤。是几乎所有后续的图像处理的基础和前提。只有根据不同场景选择不同的二值化处理,才能对一幅图片较好的初始化。(包括灰度值处理,二值化处理,根据噪声类型降噪等)。
一幅图像包括目标物体、背景还有噪声,要想从多值二值化的数字图像中直接提取出目标物体,最常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法,称为图像的二值化(BINARIZATION)。
2.阈值
2.1.阈值的定义
说到图像二值化,就不得不提到阈值,阈的意思是界限,故阈值又叫临界值,是指一个效应能够产生的最低值或最高值。
2.2.阈值类型
图像二值化的阈值有五种类型。为了解释阈值分割的过程,我们可以看一个简单有关像素灰度的图片,该图如下,该图中的蓝色水平线代表着具体的一个阈值。
2.2.1.二进制阈值化(cv2.THRESH_BINARY)
该类型如下式所示:
在运用该阈值类型的时候,先要选定一个特定的阈值量,比如:125,这样,大于125的像素点的灰度值设定为最大值(如8位灰度值最大为255),灰度值小于125的像素点的灰度值设定为0,其图解为:
2.2.2.反二进制阈值化(cv2.THRESH_BINARY_INV)
该类型的公式为:
该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值,不过最后的设定值相反。在8位灰度图中,例如大于阈值的设定为0,而小于该阈值的设定为255,其图解为:
2.2.3.截断阈值化(cv2.THRESH_TRUNC)
该类型的公式为:
首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。例如:阈值选取为125,那小于125的阈值不改变,大于125的灰度值(230)的像素点就设定为该阈值。其图解为:
2.2.4.阈值化为0(cv2.THRESH_TOZERO)
该阈值类型为:
先选定一个阈值,然后对图像做如下处理:若像素点的灰度值大于该阈值的不进行任何改变;若像素点的灰度值小于该阈值的,其灰度值全部变为0。
其图解为:
2.2.5.反阈值化为0(cv2.THRESH_TOZERO_INV)
该类型的公式为:
原理类似于0阈值,但是在对图像做处理的时候相反,若像素点的灰度值小于该阈值的不进行任何改变,而大于该阈值的部分,其灰度值全部变为0。
其图解为:
3.图像二值化方法
图像二值化方法有全局二值化,局部二值化,自定义二值化。
在进行图像二值化之前,我们都要先将图像转化为灰度图像,然后在进行相关的操作。
3.1.全局二值化
在全局二值化中,我们会用到threshold这个API,
threshold( src_gray, dst, threshold_value, max_BINARY_value, threshold_type );
其代码为:
def threshold_demo(image): # 全局二值化
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
print("threshold value: %s" % ret)
cv.imshow("binary image", binary)
原图为:
经过二值化后的图像为:
3.2.局部二值化
在局部二值化中,我们会使用到adaptiveThreshold这个API,
adaptiveThreshold( src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
src:源图像,maxValue:像素值上限,adaptiveMethod:自适应方法,
— cv2.ADAPTIVE_THRESH_MEAN_C :领域内均值
—cv2.ADAPTIVE_THRESH_GAUSSIAN_C :领域内像素点加权和,权重为一个高斯窗口
thresholdType:阈值类型,blockSize:规定领域大小(一个正方形的领域),它必须为奇数,
C:阈值等于均值或者加权值减去这个常数(为0相当于阈值 就是求得领域内均值或者加权值)
代码如下:
def local_threshold(image): # 局部二值化
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
dst = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
cv.imshow("binary image", dst)
得到的效果为:
3.3.自己计算阈值
将图像转换为灰度图像后求出其宽和高,接着将灰度图像转变成1行,w*h列的图像,然后求出平均值,最后我们再通过全局二值化来得到二值化图像。
其代码为:
def custom_threshold(image): # 自己计算阈值
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
h, w = gray.shape[:2]
m = np.reshape(gray, [1, w * h]) # 图像变成一行
mean = m.sum() / (w * h)
print("mean: ", mean)
ret, dst = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
cv.imshow("binary image", dst)
得到的效果为:
完整代码
import cv2 as cv # 导入opencv模块
import numpy as np # 导入数学函数库
def threshold_demo(image): # 全局二值化
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
"""
#大律法,全局自适应阈值 参数0可改为任意数字但不起作用
cv.THRESH_BINARY | cv.THRESH_OTSU
#TRIANGLE法,,全局自适应阈值, 参数0可改为任意数字但不起作用,适用于单个波峰
cv.THRESH_BINARY | cv.THRESH_TRIANGLE
# 自定义阈值为150,大于150的是白色 小于的是黑色
cv.THRESH_BINARY
# 自定义阈值为150,大于150的是黑色 小于的是白色
cv.THRESH_BINARY_INV
# 截断 大于150的是改为150 小于150的保留
cv.THRESH_TRUNC
# 截断 小于150的是改为150 大于150的保留
cv.THRESH_TOZERO
"""
# ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TRUNC)
print("threshold value: %s" % ret)
cv.imshow("binary image", binary)
def local_threshold(image): # 局部二值化
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
dst = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
cv.imshow("binary image", dst)
def custom_threshold(image): # 自己计算阈值
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
h, w = gray.shape[:2]
m = np.reshape(gray, [1, w * h]) # 图像变成一行
mean = m.sum() / (w * h)
print("mean: ", mean)
ret, dst = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
cv.imshow("binary image", dst)
print("------------hello python!------------")
src = cv.imread("D:/opencv3/image/house.jpg")
cv.namedWindow("input_image", cv.WINDOW_AUTOSIZE)
cv.imshow("input_image", src)
# threshold_demo(src)
# local_threshold(src)
custom_threshold(src)
cv.waitKey(0)
cv.destroyAllWindows() # 释放所有窗口