Opencv(三): 二值化
文章目录
- 一、前言
- 二、二值化的基本概念与前置条件
- 1. 核心定义
- 三、常见的六种二值化方法
- 1. 阈值法(THRESH_BINARY)
- 原理与逻辑
- 二值化代码与适用场景
- 2. 反阈值法(THRESH_BINARY_INV)
- 原理与逻辑
- 代码与适用场景
- 3. 截断阈值法(THRESH_TRUNC)
- 原理与逻辑
- 代码与适用场景
- 4. 低阈值零处理(THRESH_TOZERO)
- 原理与逻辑
- 代码与适用场景
- 5. 超阈值零处理(THRESH_TOZERO_INV)
- 原理与逻辑
- 代码与适用场景
- 6. OTSU阈值法(THRESH_OTSU)
- 原理与逻辑
- 代码实例
- 四、总结
- 1. 方法选型核心原则
- 2. 实验关键注意事项
一、前言
在计算机视觉的图像处理链路中,二值化是连接灰度化与高级任务(如轮廓提取、文字识别)的关键桥梁。它并非简单的“黑白转换”,而是通过筛选像素亮度信息,剥离冗余的灰度细节,让图像中的目标区域(如物体边缘、文字区域)与背景形成强烈对比。
二、二值化的基本概念与前置条件
1. 核心定义
二值化的本质是阈值分割:将灰度图像(像素值范围0-255)中的每个像素,依据预设规则映射为仅有的两个值——0(纯黑)和255(纯白),最终得到仅含黑白两色的二值图像。
需特别注意,二值化的操作对象**只能是灰度图像**,无法直接处理彩色图像。
三、常见的六种二值化方法
1. 阈值法(THRESH_BINARY)
原理与逻辑
作为最经典的二值化方式,它通过手动设定一个固定阈值,将像素划分为“目标”与“背景”两类:
- 当灰度像素值 大于阈值 时,判定为“目标”,赋值为255(纯白);
- 当灰度像素值 小于等于阈值 时,判定为“背景”,赋值为0(纯黑)。
二值化代码与适用场景
import cv2
import numpy as npif __name__ == "__main__":path = "./flower.png"image_np = cv2.imread(path)image_np = cv2.resize(image_np,(400,400))img_shape = image_np.shapeimage_np_gray = np.zeros((img_shape[0], img_shape[1]), dtype=np.uint8) # image_np.copy()# 加权灰度化wr = 0.299wg = 0.587wb = 0.114for i in range(img_shape[0]):for j in range(img_shape[1]):image_np_gray[i, j] = (int(wr * image_np[i, j][2]) + int(wg * image_np[i, j][1]) + int(wb * image_np[i, j][0]))# 二值化ret, image_np_thresh = cv2.threshold(image_np_gray, 127, 255, cv2.THRESH_BINARY)cv2.imshow("image_np_gray", image_np_gray)cv2.imshow("image_np_thresh", image_np_thresh)cv2.waitKey(0)
输出结果为:
灰度化:

二值化图像:

适用场景:光照均匀、目标与背景亮度差异显著的图像,如实验室环境下拍摄的物体、无阴影的文档扫描图。
2. 反阈值法(THRESH_BINARY_INV)
原理与逻辑
与阈值法完全相反,通过反转黑白映射规则,实现“背景变目标、目标变背景”的效果:
- 当灰度像素值 大于阈值 时,赋值为0(纯黑);
- 当灰度像素值 小于等于阈值 时,赋值为255(纯白)。
代码与适用场景
import cv2
import numpy as np#1.读取要二值化的彩色图
image_np = cv2.imread('./flower.png')
image_np = cv2.resize(image_np, (400, 400))#2.将读取到的彩色图进行灰度化
image_gray = cv2.cvtColor(image_np,cv2.COLOR_BGR2GRAY)#获取灰度图的形状
image_shape = image_gray.shape#创建一个二值化模板
image_thresh = np.zeros((image_shape[0],image_shape[1]),dtype=np.uint8)#设置阈值
thresh = 127
#设置最大值
maxval = 255ret,image_thresh = cv2.threshold(image_gray,thresh,maxval,cv2.THRESH_BINARY_INV)cv2.imshow('image_thresh',image_thresh)
cv2.waitKey(0)
输出结果为:

适用场景:需要突出暗部目标的场景,如提取图像中的阴影区域、检测透明物体在亮背景下的轮廓。
3. 截断阈值法(THRESH_TRUNC)
原理与逻辑
与前两种方法不同,它不产生纯黑像素,而是通过“截断”亮度上限来压缩灰度范围:
- 当灰度像素值 大于阈值 时,强制赋值为阈值(而非255);
- 当灰度像素值 小于等于阈值 时,保持原像素值不变。
最终二值图(实际为“灰度受限图”)的最大像素值等于设定的阈值,不会出现纯白区域。
代码与适用场景
import cv2
import numpy as npimage_np = cv2.imread('./flower.png')
image_np = cv2.resize(image_np, (400, 400))image_gray = cv2.cvtColor(image_np,cv2.COLOR_BGR2GRAY)thresh = 150
maxval = 255image_shape = image_gray.shapeimage_thresh = np.zeros((image_shape[0],image_shape[1]),dtype = np.uint8)ret,image_thresh = cv2.threshold(image_gray,thresh,maxval,cv2.THRESH_TRUNC)cv2.imshow('image_thresh',image_thresh)
cv2.waitKey(0)
输出结果为:

适用场景:需要保留暗部细节、抑制高亮过曝的场景,如处理逆光拍摄的图像、保留金属表面的反光层次。
4. 低阈值零处理(THRESH_TOZERO)
原理与逻辑
聚焦于“消除暗部干扰”,仅对低亮度像素进行处理:
- 当灰度像素值 小于等于阈值 时,赋值为0(纯黑),彻底消除暗部噪声;
- 当灰度像素值 大于阈值 时,保持原像素值不变,保留亮部的灰度细节。
代码与适用场景
import cv2
import numpy as npimage_np = cv2.imread('./flower.png')
image_np = cv2.resize(image_np, (400, 400))image_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)thresh = 150
maxval = 255 ret, image_thresh = cv2.threshold(image_gray, thresh, maxval, cv2.THRESH_TOZERO)cv2.imshow('image_thresh', image_thresh)
cv2.waitKey(0)
输出结果为:

适用场景:暗部存在噪声(如 grain 噪点),但亮部目标清晰的图像,如夜间监控中识别灯光下的物体。
5. 超阈值零处理(THRESH_TOZERO_INV)
原理与逻辑
与低阈值零处理相反,专注于“保留暗部目标”,抑制亮部干扰:
- 当灰度像素值 大于阈值 时,赋值为0(纯黑),消除亮部噪声;
- 当灰度像素值 小于等于阈值 时,保持原像素值不变,保留暗部细节。
代码与适用场景
import cv2
import numpy as npimage_np = cv2.imread('./flower.png')
image_np = cv2.resize(image_np, (400, 400))image_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)thresh = 150
maxval = 255 ret, image_thresh = cv2.threshold(image_gray, thresh, maxval, cv2.THRESH_TOZERO_INV)cv2.imshow('image_thresh', image_thresh)
cv2.waitKey(0)
输出结果为:

适用场景:亮部存在干扰(如反光、光斑),暗部目标为核心分析对象的场景,如医学图像中观察组织的暗部病灶。
6. OTSU阈值法(THRESH_OTSU)
原理与逻辑
前五种方法均需手动设定阈值,但实际场景中(如摄像头拍摄的动态图像),光照变化会导致固定阈值失效。OTSU算法通过最大化类间方差,自动计算出最优阈值,无需人工干预。
其核心逻辑是:将灰度图的像素划分为“前景”(目标)和“背景”两类,遍历0-255所有可能的阈值,找到使两类像素的方差最大的阈值——方差越大,说明前景与背景的亮度差异越显著,分割效果越好。
代码实例
import cv2
import numpy as npimage_np = cv2.imread('./flower.png')
image_np = cv2.resize(image_np, (400, 400))image_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)# OTSU法中手动阈值设为0,由算法自动计算
thresh = 0
maxval = 255# 关键修改:方法叠加cv2.THRESH_OTSU(此处以THRESH_BINARY为例,也可叠加其他类型如THRESH_BINARY_INV)
ret, image_thresh = cv2.threshold(image_gray, thresh, maxval, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 打印OTSU算法自动计算的最优阈值
print(f"OTSU自动计算的最优阈值:{ret}")cv2.imshow('image_thresh', image_thresh)
cv2.waitKey(0)
输出结果为:

- 注意事项:使用OTSU时,手动设定的
thresh参数会失效,最终阈值由算法计算得出;该方法对噪声敏感,建议先通过高斯模糊(cv2.GaussianBlur)预处理图像,再进行OTSU二值化。 - 适用场景:光照不均、场景动态变化的图像,如实时监控画面、不同角度拍摄的产品图。
四、总结
1. 方法选型核心原则
通过实验对比,六种方法的适用场景可总结为“三看”:
- 看光照:光照均匀用手动阈值法(如THRESH_BINARY),光照不均用OTSU自适应法;
- 看目标:目标是亮部用THRESH_BINARY/TOZERO,目标是暗部用THRESH_BINARY_INV/TOZERO_INV;
- 看需求:需保留灰度细节用THRESH_TRUNC,需纯黑白对比用其他五种方法。
2. 实验关键注意事项
- 图像格式:实验中导入的图像需为原生PNG格式,避免由JPG等格式修改后缀导致的读取错误,影响二值化效果;
- OTSU预处理:当图像存在噪声时,直接用OTSU会导致阈值计算偏差,建议先执行
src = cv2.GaussianBlur(src, (5,5), 0)(5×5高斯核)去噪; - 参数验证:手动设定阈值时,可多尝试127(中间值)、150、200等常用值,通过对比二值图效果选择最优阈值,而非依赖固定值。
