contribute上次修改:2026-09-29

2.5 二值化与阈值

总目录:1.1 OpenCV介绍与学习路线 | 第二章:基础图像处理 | 编号:2.5

← 上一节:2.4 滤波与降噪 | 下一节:2.6 形态学处理 →


2.5 二值化与阈值

二值化做的事情非常朴素:给每个像素安排一次“站队”,最后只留下前景与背景。轮廓算法不想面对五颜六色的世界,它更喜欢一张边界明确的黑白图。

一、阈值是在做像素分类

以最常见的二值阈值为例:

像素值 > 阈值 → 255(白)
否则          → 0(黑)

阈值不是天然真理。光照、曝光、材质变了,同一个数可能就不合适了。

二、固定阈值 threshold

used_threshold, binary = cv2.threshold(
    gray,
    127,
    255,
    cv2.THRESH_BINARY,
)

参数:

参数 含义
gray 输入图,常见情况是单通道灰度图
127 分类阈值
255 满足条件时写入的最大值
THRESH_BINARY 阈值规则

返回两个值:真正使用的阈值和结果图。普通固定阈值里第一个返回值通常就是传入的 127;使用 Otsu 时它才尤其有用。

五种基础规则

类型 规则概念
THRESH_BINARY 高于阈值变白,其余变黑
THRESH_BINARY_INV 高于阈值变黑,其余变白
THRESH_TRUNC 高于阈值的部分压到阈值
THRESH_TOZERO 低于阈值的部分归零
THRESH_TOZERO_INV 高于阈值的部分归零

做轮廓时最常用前两种。因为 findContours 主要把白色区域当作前景,所以黑色目标落在白背景上时,经常需要 THRESH_BINARY_INV。

三、自适应阈值 adaptiveThreshold

一张纸左边亮、右边暗时,一个全局阈值可能怎么选都难受。自适应阈值会根据每个像素附近的小区域算局部阈值:

binary = cv2.adaptiveThreshold(
    gray,
    255,
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv2.THRESH_BINARY,
    blockSize=11,
    C=2,
)
  • blockSize:邻域大小,必须是大于 1 的奇数;
  • C:从局部均值或加权均值里减去的常数;
  • MEAN_C:普通邻域均值;
  • GAUSSIAN_C:按高斯权重计算邻域均值。

自适应不等于自动完美。块太小会追着纹理跑,块太大又接近全局阈值。

四、Otsu:自动寻找全局阈值

Otsu 会根据灰度直方图选择一个全局阈值,适合前景和背景大致形成两个峰的图像:

used_threshold, binary = cv2.threshold(
    gray,
    0,
    255,
    cv2.THRESH_BINARY + cv2.THRESH_OTSU,
)
print("Otsu threshold:", used_threshold)
2.5-image-001

噪声会搅乱直方图,常先轻度高斯滤波:

blurred = cv2.GaussianBlur(gray, (5, 5), 0)
_, binary = cv2.threshold(
    blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
)

五、三种方法怎样选

光照稳定、速度优先       → 固定阈值
同一画面有明显明暗不均   → 自适应阈值
直方图双峰、想自动全局选 → Otsu
按颜色而不是亮度分割     → [HSV + inRange](/notes/OpenCV%E5%85%A5%E9%97%A8/2.7%20HSV%E9%A2%9C%E8%89%B2%E6%A3%80%E6%B5%8B)

调参时别只看最终框

同时显示:

cv2.imshow("Gray", gray)
cv2.imshow("Binary", binary)

若目标在二值图里已经断了、粘了或前景背景反了,后面的轮廓参数救不了它。先把这一层做好,再去调面积阈值。

六、参考


← 上一节:2.4 滤波与降噪 | 下一节:2.6 形态学处理 →

留言区

不收集任何个人信息;昵称只绑定浏览器里的随机 Cookie。