OpenCV图像二值化实战:全局阈值、自适应与Otsu算法深度解析

1. 二值化:从“黑白分明”说起

大家好,我是老张,在图像处理这行摸爬滚打十来年了。今天咱们聊一个听起来很专业,但实际应用无处不在的技术——图像二值化。简单来说,二值化就是把一张彩色的或者灰度的图片,变成只有纯黑和纯白两种颜色的图片。这个过程,就像是把一张复杂的素描画,用最粗的马克笔重新描一遍,只留下最核心的轮廓和形状。

你可能会问,好好的图片为什么要变成黑白两色?这用处可太大了。比如,你手机上的扫描软件,能把一张纸质发票拍下来,自动识别上面的文字和数字,背后很可能就用到了二值化技术,先把背景和文字分离开。再比如,工厂里用摄像头检查产品上有没有划痕或瑕疵,第一步往往也是把图像二值化,让缺陷在黑白背景下变得一目了然。还有我们熟悉的二维码识别,第一步也是把图像变成黑白分明的样子,方便机器“阅读”。

在OpenCV这个强大的计算机视觉库中,实现二值化最核心的函数就是 cv2.threshold()。别看它只是一个函数,里面却藏着好几种不同的玩法,从最简单的“一刀切”全局阈值,到聪明的“因地制宜”自适应阈值,再到能自己找最佳分割点的Otsu算法。接下来,我就带你深入浅出地走一遍,结合大量我实际项目中踩过的坑和总结的经验,让你不仅能看懂代码,更能知道在什么情况下该用什么方法。

2. 全局阈值:简单粗暴的“一刀切”

2.1 核心函数与五种“刀法”

全局阈值,顾名思义,就是给整张图片设定一个固定的门槛值。OpenCV的 cv2.threshold() 函数就是这个“执刀人”。它的基本语法是这样的:

retval, dst = cv2.threshold(src, thresh, maxval, type)

我习惯把参数拆开揉碎了理解:

  • src:待处理的源图像。这里有个关键点:虽然函数说明里说可以是多通道,但为了稳妥起见,我强烈建议你先用 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 转换成灰度图再处理,避免色彩通道带来的意外。
  • thresh:你设定的那个“门槛”,比如经典的127。
  • maxval:当像素值超过(或低于)门槛时,要被赋予的新值,通常是255(白色)。
  • type:这是“刀法”的选择器,决定了怎么砍这一刀。它直接决定了二值化的效果。
  • retval:函数返回的实际使用的阈值,在普通全局阈值里,它就是你设定的 thresh;但在Otsu算法里,它会变成算法找到的最佳阈值。
  • dst:处理后的结果图像。

这个 type 参数有五种主要“刀法”,我用一个简单的灰度渐变图来给你直观展示一下区别。假设我们有一幅从纯黑(0)到纯白(255)均匀渐变的图像,设定阈值 thresh=127maxval=255

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

# 创建一个简单的水平渐变灰度图(0到255)
gradient = np.tile(np.linspace(0, 255, 256, dtype=np.uint8), (100, 1))

ret, thresh_binary = cv2.threshold(gradient, 127, 255, cv2.THRESH_BINARY)
ret, thresh_binary_inv = cv2.threshold(gradient, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh_trunc = cv2.threshold(gradient, 127, 255, cv2.THRESH_TRUNC)
ret, thresh_tozero = cv2.threshold(gradient, 127, 255, cv2.THRESH_TOZERO)
ret, thresh_tozero_inv = cv2.threshold(gradient, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Gradient', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [gradient, thresh_binary, thresh_binary_inv, thresh_trunc, thresh_tozero, thresh_tozero_inv]

plt.figure(figsize=(12, 6))
for i in range(6):
    plt.subplot(2, 3, i+1)
    plt.imshow(images[i], cmap='gray', vmin=0, vmax=255)
    plt.title(titles[i])
    plt.axis('off')
plt.tight_layout()
plt.show()

运行这段代码,你会看到六张小图,效果差异一目了然。下面我结合这个渐变图,用大白话解释每种“刀法”:

cv2.THRESH_BINARY(二值化):这是最经典的。像素值 > 127的,全变成255(白);像素值 <= 127的,全变成0(黑)。结果就是渐变图中间被一刀切开,左边全黑,右边全白。

cv2.THRESH_BINARY_INV(反二值化):跟上面正好反过来。像素值 > 127的,变黑(0);像素值 <= 127的,变白(255)。相当于把黑白区域对调了。

cv2.THRESH_TRUNC(截断):这个比较有意思,它不产生纯二值图。像素值 > 127的

代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统中修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程中所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统中,网络配置的管理机制早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此类问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值