机器视觉学习-day03-灰度化实验-二值化和自适应二值化

1 二值化

二值化就是将某张图片的像素改成只有两种值(最常见的是纯黑和纯白),二值化操作的图像必须是灰度图,二值化的过程实际上是将一张灰度图上的像素根据某种规则修改为两种数值(0和maxval),使图像呈现出更为强烈的黑白效果,可以帮助后续处理图像轮廓或边缘等特征。

代码步骤:图片输入→灰度化→二值化→图片输出

1.1 阈值法(THRESH_BINARY)

阈值法就是通过设定一个阈值thresh,将灰度图的每一个像素与该阈值进行比较,小于等于阈值的像素被设置为0(黑),大于阈值的像素被设置为maxval(255-白)。

图片名为:1.png

复制代码
import cv2
import numpy as np

# 程序主入口
if __name__ == '__main__':
    # 1. 读取图像并转换为灰度图
    image = cv2.imread('image.jpg')  # 读取原始彩色图像
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 转换为灰度图:加权平均法

    """
    详细解释:
    cv2.imread():从指定路径读取图像,返回一个NumPy数组
    cv2.cvtColor(..., cv2.COLOR_BGR2GRAY): 将BGR彩色图像转换为灰度图像
    """

    # 2. 设置阈值
    threshold_value = 128  # 中间值(0-255之间)

    """
    阈值选择:
    - 128是0-255的中间值
    - 可以根据具体图像调整此值(范围0-255)
    """

    # 3. 创建结果图像
    threshold_image = np.zeros_like(gray_image)  # 创建与灰度图相同大小的全黑图像

    """
    np.zeros_like() - 创建一个与输入数组形状和类型相同的全零数组
    这里用于存储阈值处理后的结果
    """

    # 4.图片矫正. 获取图像尺寸
    height, width = gray_image.shape

    # 5. 应用阈值法
    for i in range(height):
        for j in range(width):
            # 获取当前像素值
            pixel_value = gray_image[i, j]

            # 阈值法判断
            if pixel_value >= threshold_value:
                threshold_image[i, j] = 255  # 设为白色
            else:
                threshold_image[i, j] = 0  # 设为黑色
            # 如果像素灰度值 > 127:设为255(纯白)
            # 如果像素灰度值 ≤ 127:设为0(纯黑)

    """
    阈值法逻辑:
    - 遍历图像的每个像素
    - 如果像素值 >= 阈值,设为白色(255)
    - 如果像素值 < 阈值,设为黑色(0)
    """

    # 6. 显示结果
    cv2.imshow('Original Gray Image', gray_image)  # 原始灰度图
    cv2.imshow('Thresholding (T={})'.format(threshold_value), threshold_image)  # 阈值法结果

    # 7. 等待按键关闭窗口
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    # 8. 保存结果
    cv2.imwrite('threshold_result.png', threshold_image)

    """
    结果说明:
    - 原始灰度图:连续色调的灰度图像
    - 阈值法结果:二值图像(只有黑白两种颜色)
    - 明亮区域(>=阈值)变为白色
    - 暗区域(<阈值)变为黑色
    """

1.2 反阈值法(THRESH_BINARY_INY)

反阈值法与阈值法相反,当灰度图的像素值大于阈值时,像素值会被设置为0;当灰度图的像素值小于等于阈值时,像素值会被设置为最大值。

python 复制代码
# 反阈值法(THRESH_BINARY_INV)

import cv2

if __name__ == '__main__':
    # 1. 图片输入
    path = '1.jpg'  # 指定图片文件路径
    image_np = cv2.imread(path)  # 读取图片到NumPy数组,格式为BGR三通道

    # 2. 灰度化(调用接口)
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)  # BGR→灰度
    # 将彩色图像转为单通道灰度图像,因为二值化需要单通道输入
    """
    详细解释:
    cv2.imread(path): 从指定路径读取图像
    cv2.cvtColor(..., cv2.COLOR_BGR2GRAY): 将BGR彩色图像转换为灰度图像
    """

    # 3. 二值化
    thresh = 127  # 阈值
    maxval = 255  # 最大值
    # 二值化
    # 返回值1:阈值(thresh的值,部分算法是自动计算的,本例没用)
    # 返回值2:二值化之后的图片
    ret, image_np_gray = cv2.threshold(
        image_np_gray,  # 输入的灰度图像
        thresh,  # 阈值
        maxval,  # 最大值
        cv2.THRESH_BINARY_INV  # 二值化类型,反阈值即反向二值化
    )

    # 4.图片矫正. 图片输出
    cv2.imshow('image_np_gray', image_np_gray)
    cv2.waitKey(0)
    cv2.imwrite('INV.png', image_np_gray)

1.3 其他阈值法(了解即可)

1.3.1 截断阈值法(THRESH_TRUNC)

截断阈值法是将灰度图中所有像素值与阈值比较,当像素值大于阈值时被修改为为阈值,小于等于阈值的部分不变。

1.3.2 低阈值零处理(THRESH_TOZERO)

低阈值零处理表示像素值小于等于阈值的部分被设置为0,大于阈值的部分不变。

1.3.3 超阈值零处理(THRESH_TOZERO_INV)

超阈值零处理表示像素值大于阈值的部分被设置为0,小于等于阈值的部分不变。

1.4 OTSU阈值法

以上的二值化方法都需要手动设置阈值,但是在不同的环境下,摄像头拍摄的图像可能存在差异,导致手动设置的阈值并不适用于所有图像,这可能会使二值化的效果不理想。因此需要一种自动计算图片阈值的二值化方法,可以提高图像处理的准确性和鲁棒性。

使用 OTSU 阈值法可以找到一张图片的阈值,需要注意的是,这种方法仅用于找到阈值,并不能二值化,是在二值化之前增加的算法。OTSU算法就是通过一个值把图片分为前景色和背景色,通过统计学的方法来验证该值的合理性:最大类间方差。

通过OTSU算法得到阈值T之后,就可以结合之前的任意一种二值化方法进行操作,在虚拟仿真实验中只提供了两种二值化与OTSU结合的方式:

  1. THRESH_BINARY + THRESH_OTSU :阈值法+OTSU

  2. THRESH_BINARY_INT + THRESH_OTSU :反阈值法+OTSU

python 复制代码
import cv2

if __name__ == '__main__':
    # 1. 图片输入
    path = '1.jpg'  # 读取原始彩色图像
    image_np = cv2.imread(path)
    # 2. 灰度化
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)  # BGR→灰度
    """
      详细解释:
      - cv2.imread() 读取图像,返回NumPy数组
      - cv2.cvtColor() 将BGR图像转换为灰度图像
      """

    # 3. 二值化
    thresh = 145  # 阈值
    maxval = 255  # 最大值
    # 二值化
    # 返回值1:OTSU计算的阈值
    # 返回值2:二值化之后的图片
    ret, image_np_gray = cv2.threshold(
        image_np_gray,  # 灰度图
        thresh,  # 阈值
        maxval,  # 最大值
        cv2.THRESH_BINARY + cv2.THRESH_OTSU  # OTSU+二值化
    )
    """
    cv2.threshold()参数说明:
      image_np_gray: 输入灰度图像
      在这个函数里thresh==0: 因为使用OTSU,这里设为0(会被忽略)
      maxval/255: 最大值(白色)
      cv2.THRESH_BINARY + cv2.THRESH_OTSU: 阈值法 + OTSU算法

    返回值:
      ret,: OTSU算法计算出的最佳阈值
      image_np_gray : 阈值处理后的图像(这里不需要,因为我们后面会自己处理)

    OTSU 算法原理:
    1. 计算图像灰度
    2. 遍历所有可能的阈值(0-254)
    3. 对每个阈值,将像素分为两类(前景和背景)
    4.图片矫正. 计算两类之间的方差(类间方差)
    5. 选择使类间方差最大的阈值作为最佳阈值
    """
    print(f"OTSU算法计算的最佳阈值: {ret}")
    # OTSU算法计算的最佳阈值: 123.0

    # 4.图片矫正. 图片输出
    cv2.imshow('image_np_gray', image_np_gray)
    cv2.waitKey(0)
    cv2.imwrite('OTSU.png', image_np_gray)

2 自适应二值化

自适应二值化更加适合明暗分布不均匀的图片。自适应二值化会对图像的所有像素点单独计算阈值,这样更好的针对每个像素点判断是前景还是背景。自适应二值化可以更好的保留图片的信息。

代码运行步骤:图片输入→灰度化→自适应二值化→图片输出

代码参数:

参数:

maxval:最大值,通常为255

adaptiveMethod:小区域阈值的计算方式

ADAPTIVE_THRESH_MEAN_C:小区域内取均值

ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核

thresholdType:二值化方法

THRESH_BINARY 阈值法

THRESH_BINARY_INV 反阈值法

blockSize:小区域的面积,通常取奇数,例如7表示7*7,后期称之为核(各种滤波和卷积等都用的到),计算的方式为滑动(从左到右,从上到下)计算

c:最终阈值等于计算的阈值减去此值

1 取均值 ADAPTIVE_THRESH_MEAN_C

python 复制代码
import cv2

if __name__ == '__main__':
    # 1. 图片输入
    path = '1.jpg'
    image_np = cv2.imread(path)  # 读取原始彩色图像

    # 2. 灰度化(为了手搓二值化,暂时手搓灰度化)
    image_np_gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY)  # BGR→灰度
    # 将彩色图像转为单通道灰度图像,因为二值化需要单通道输入

    # 3. 自适应二值化
    maxval = 255  # 二值化后的最大值(白色)
    # 自适应二值化
    # 返回值:自适应二值化之后的图像
    image_np_adaptive = cv2.adaptiveThreshold(
        image_np_gray,  # 要处理的灰度化图像
        maxval,  # 当像素值超过阈值时赋予的值(255=白色)
        cv2.ADAPTIVE_THRESH_MEAN_C,  # 自适应方法:使用邻域均值计算阈值
        # 另一种选项是 cv2.ADAPTIVE_THRESH_GAUSSIAN_C,使用高斯加权平均值
        cv2.THRESH_BINARY_INV,  # 阈值法还是反阈值法
        # 二值化模式:反向二值化(大于阈值变0/黑,小于变255/白)
        11,  # 核大小(邻域窗口尺寸)
        10,  # C值(从均值中减去的常数)
    )

    # 4.图片矫正. 图片输出
    cv2.imshow('image_np_adaptive', image_np_adaptive)  # 显示二值化结果
    cv2.waitKey(0)  # 等待按键后关闭窗口
    cv2.imwrite('zishiying.png',image_np_adaptive)
相关推荐
IT_陈寒几秒前
Python 3.12 新特性实战:5个让你的代码效率提升50%的技巧!🔥
前端·人工智能·后端
我们从未走散6 分钟前
设计模式学习笔记-----抽象责任链模式
java·笔记·学习·设计模式·责任链模式
点云SLAM14 分钟前
PyTorch中 nn.Linear详解和实战示例
人工智能·pytorch·python·深度学习·cnn·transformer·mlp
Magnetic_h21 分钟前
【iOS】内存管理及部分Runtime复习
笔记·学习·macos·ios·objective-c·cocoa·xcode
双翌视觉32 分钟前
机器视觉的3C玻璃盖板丝印应用
数码相机·计算机视觉·视觉检测
耳东哇35 分钟前
在使用spring ai进行llm处理的rag的时候,选择milvus还是neo4j呢?
人工智能·neo4j·milvus
过往入尘土40 分钟前
深入浅出 PyTorch:从下载安装到核心知识点全解析
人工智能·pytorch·python
youcans_1 小时前
【AGI使用教程】GPT-OSS 本地部署(2)
人工智能·gpt·大语言模型·模型部署·webui
鲸鱼24011 小时前
支持向量机
人工智能·机器学习·支持向量机
CoovallyAIHub1 小时前
无需ReID网络!FastTracker凭借几何与场景认知实现多目标跟踪新SOTA,助力智慧交通更轻更快
深度学习·算法·计算机视觉