当前位置: 首页 > article >正文

opencv之阈值处理

文章目录

  • 1. 阈值处理
  • 2. 阈值处理的基本原理
  • 3. 常见的阈值处理方法
    • 3.1 全局阈值(Global Thresholding):
    • 3.2 自适应阈值(Adaptive Thresholding):
      • 3.2.1 工作原理
      • 3.2.2 工作步骤
      • 3.2.3 适用场景
      • 3.2.4 优缺点
        • 自适应阈值的优点
        • 自适应阈值的缺点
    • 3.3 Otsu’s 方法:
      • 什么是最大化类间方差
      • 工作原理
      • 适用场景
      • 优缺点
  • 4. 应用场景
  • 总结

1. 阈值处理

在图像处理领域,阈值处理(Thresholding)是一种简单而有效的技术,用于将灰度图像转化为二值图像(即每个像素点要么是黑色,要么是白色)。这种处理方式常用于分割图像中的前景和背景,或者提取特定的形状或物体。

2. 阈值处理的基本原理

阈值处理的基本思想是设定一个阈值 T T T,然后遍历图像中的每一个像素。如果像素的灰度值高于阈值,就将其设为白色(通常为255);如果低于阈值,则将其设为黑色(通常为0)。公式如下:

g ( x , y ) = { 255 , i f f ( x , y ) > T 0 , i f f ( x , y ) ≤ T (1) g(x,y)= \begin{cases} 255,if\quad f(x,y)>T\\ 0, if\quad f(x,y)\leq T \end{cases} \tag{1} g(x,y)={255,iff(x,y)>T0,iff(x,y)T(1)
其中, f ( x , y ) f(x,y) f(x,y) 是原始图像的灰度值, g ( x , y ) g(x,y) g(x,y) 是处理后的二值图像。

3. 常见的阈值处理方法

3.1 全局阈值(Global Thresholding):

  • 在这种方法中,整个图像使用同一个阈值。适合于图像对比度较高且背景简单的情况。OpenCV 中常用的函数是 cv2.threshold
import cv2

# 读取灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 全局阈值处理
_, thresh_global = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# 显示结果
cv2.imshow('Global Thresholding', thresh_global)
cv2.waitKey(0)
cv2.destroyAllWindows()

3.2 自适应阈值(Adaptive Thresholding):

自适应阈值方法会根据图像的局部区域动态计算阈值,因此对于光照不均或对比度较低的图像更有效。自适应阈值根据局部窗口内的像素值计算每个像素的阈值,从而避免了全局阈值对整个图像的统一处理。

3.2.1 工作原理

自适应阈值(Adaptive Thresholding)的工作原理是根据图像局部区域的特征来动态调整阈值,从而处理光照不均或对比度不够的图像。它的主要思想是对于图像中的每一个像素,根据其周围邻域的像素值来确定一个局部阈值。这样可以避免全局阈值方法可能带来的效果不佳的问题,尤其是在图像的不同区域光照差异较大的情况下。

  • 计算临近区域的加权平均值:

对于图像中的每一个像素点,自适应阈值方法会考虑该像素点周围的一定范围内的像素值。这些像素值形成了一个局部区域或窗口。
通过计算这个局部区域内的像素值的加权平均(或均值),得到一个阈值。加权平均意味着某些像素对计算结果的影响比其他像素更大,通常是窗口中心的像素权重更高。

  • 获得阈值:

计算出的加权平均值(或均值)被用作该像素点的局部阈值。这个阈值代表了该像素所在局部区域的“亮度”水平。

  • 对当前像素点进行处理:

使用计算得到的局部阈值来决定该像素点的类别。具体地说:
如果当前像素的值大于或等于局部阈值,则将其分类为前景(通常设为 255,白色)。
如果当前像素的值小于局部阈值,则将其分类为背景(通常设为 0,黑色)。

3.2.2 工作步骤

1. 局部邻域计算:

  • 将图像划分为多个小的局部区域(通常称为窗口或块),在每个局部区域内计算一个局部阈值。这个局部阈值基于该区域内的像素值来动态确定。

2. 局部阈值计算:

对于每个局部区域,计算其局部阈值的常用方法包括均值和高斯加权平均:

  • 均值自适应阈值(Adaptive Mean Thresholding): 阈值等于邻域像素的平均值减去一个常量。公式如下:

    • 公式: T ( x , y ) = m e a n ( I ( x , y ) ) − C T(x,y)=mean(I(x,y))−C T(x,y)=mean(I(x,y))C

    • 其中:

      • T ( x , y ) T(x,y) T(x,y)是位置 ( x , y ) (x,y) (x,y) 的阈值。
      • m e a n ( I ( x , y ) ) mean(I(x,y)) mean(I(x,y)) 是位置 ( x , y ) (x,y) (x,y) 的邻域内像素的平均值。
      • C C C 是一个常数,用于调整阈值。

​ 在这种方法中,阈值是由邻域内像素的均值减去一个常数 C C C计算得到的。常数 C C C用于避免噪声对分割结果的影响。

  • 高斯自适应阈值(Adaptive Gaussian Thresholding): 阈值等于邻域像素的加权平均值(权重为高斯窗口)减去一个常量。公式如下:

    • T ( x , y ) = m e a n ( I ( x , y ) ) − C ⋅ s t d ( I ( x , y ) ) T(x,y)=mean(I(x,y))−C⋅std(I(x,y)) T(x,y)=mean(I(x,y))Cstd(I(x,y))
    • 其中:
      • T ( x , y ) T(x,y) T(x,y) 是位置 ( x , y ) (x,y) (x,y) 的阈值。
      • m e a n ( I ( x , y ) ) mean(I(x,y)) mean(I(x,y)) 是位置 ( x , y ) (x,y) (x,y)的邻域内像素的平均值。
      • s t d ( I ( x , y ) ) std(I(x,y)) std(I(x,y)) 是位置 ( x , y ) (x,y) (x,y)的邻域内像素的标准差。
      • C C C是一个常数,用于调整阈值。

    在这种方法中,阈值是由邻域内像素的均值减去标准差的 C C C倍计算得到的。这样可以更好地处理局部的光照变化和噪声。

3.二值化处理:

  • 对于每个像素点,将其灰度值与计算得到的局部阈值进行比较。如果灰度值大于局部阈值,则将其设置为白色;否则,设置为黑色。

3.2.3 适用场景

  • 图像光照不均匀或有明显的阴影。
  • 需要在复杂背景下进行分割。

3.2.4 优缺点

自适应阈值的优点
  • 适应光照变化: 能够处理光照不均匀的图像,避免全局阈值方法对不同区域处理不一致的问题。
  • 局部处理: 通过局部窗口计算阈值,可以更好地处理细节和复杂背景。
自适应阈值的缺点
  • 计算复杂度较高: 由于需要对每个像素计算局部阈值,处理时间相对较长。
  • 参数选择: 自适应阈值方法中的参数(如窗口大小和常量)需要根据具体图像调整,以获得最佳效果。
import cv2

# 读取灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 自适应均值阈值处理
thresh_mean = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
                                    cv2.THRESH_BINARY, 11, 2)

# 自适应高斯阈值处理
thresh_gaussian = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                        cv2.THRESH_BINARY, 11, 2)

# 显示结果
cv2.imshow('Adaptive Mean Thresholding', thresh_mean)
cv2.imshow('Adaptive Gaussian Thresholding', thresh_gaussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

自定义实现(不使用 OpenCV)

如果你需要从头开始实现自适应阈值处理,以下是一个简化的 Python 代码示例:

import numpy as np
import cv2

def adaptive_threshold(image, block_size, C):
    rows, cols = image.shape
    padded_image = np.pad(image, pad_width=block_size//2, mode='constant', constant_values=0)
    result = np.zeros_like(image)

    for i in range(rows):
        for j in range(cols):
            block = padded_image[i:i+block_size, j:j+block_size]
            mean = np.mean(block)
            threshold = mean - C
            result[i, j] = 255 if image[i, j] >= threshold else 0

    return result

# 读取图像(以灰度模式)
image = cv2.imread('input_image.png', cv2.IMREAD_GRAYSCALE)

# 设置自适应阈值参数
block_size = 11
constant = 2

# 计算自适应阈值
adaptive_thresh = adaptive_threshold(image, block_size, constant)

# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Adaptive Threshold', adaptive_thresh)

# 等待按键并销毁窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

# 保存处理后的图像(可选)
cv2.imwrite('adaptive_thresh_custom.png', adaptive_thresh)

3.3 Otsu’s 方法:

Otsu’s 阈值法是一种自动选择阈值的全局方法。它通过分析图像的灰度直方图,找到能够最大化类间方差(前景和背景)的阈值。Otsu’s 方法适用于双峰分布的图像(即前景和背景的灰度值分布相对独立且存在两个峰值)。

什么是最大化类间方差

最大化类间方差(Between-Class Variance)是 Otsu’s 阈值法的核心概念,旨在选择一个最佳阈值,使得图像的前景和背景之间的差异最大化。这种方法通过分析图像的灰度直方图,找到一个阈值,使得图像被分割成前景和背景后,它们之间的类间方差最大。

工作原理

Otsu’s 方法遍历所有可能的阈值,并计算每个阈值对应的类间方差,选择使类间方差最大的阈值作为最终的阈值。

适用场景

  • 图像的灰度直方图呈现双峰分布。
  • 需要自动选择最优阈值。

优缺点

  • 优点: 自动选择阈值,适用于双峰图像的分割。
  • 缺点: 对多峰分布的图像效果不佳,计算量相对较大。

公式推导链接:https://blog.csdn.net/leonardohaig/article/details/120269341

OpenCV 中可以通过设置 cv2.THRESH_OTSU 来使用。

import cv2

# 读取灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# Otsu's 阈值处理
_, thresh_otsu = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 显示结果
cv2.imshow('Otsu Thresholding', thresh_otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()

代码

import cv2
import numpy as np

# 读取图像并转换为灰度图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 全局阈值处理
_, thresh_global = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# 自适应阈值处理
thresh_adaptive = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
                                        cv2.THRESH_BINARY, 11, 2)

# Otsu's 阈值处理
_, thresh_otsu = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 显示结果
cv2.imshow('Global Thresholding', thresh_global)
cv2.imshow('Adaptive Thresholding', thresh_adaptive)
cv2.imshow('Otsu Thresholding', thresh_otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 应用场景

  • 文档图像的二值化:用于将扫描的文档图像转换为黑白图像,以便进一步的 OCR(光学字符识别)处理。
  • 物体检测:在自动化检测系统中,阈值处理可以用于分割目标物体,以便进行形状分析或特征提取。
  • 医学图像处理:用于分割细胞、器官或其他生物结构。

阈值处理是图像预处理中常用的步骤,尤其适合对噪声较少、对比度较高的图像进行处理。根据具体应用的需要,可以选择合适的阈值处理方法。

总结

  • 全局阈值适合简单、光照均匀的图像,计算速度快但对复杂场景效果不好。
  • 自适应阈值适合光照不均的复杂图像,能更好地处理细节,但计算复杂度较高。
  • Otsu’s 阈值法是一种自动选择阈值的全局方法,适合灰度直方图呈双峰分布的图像。

http://www.kler.cn/a/284586.html

相关文章:

  • 【2024软考架构案例题】你知道 Es 的几种分词器吗?Standard、Simple、WhiteSpace、Keyword 四种分词器你知道吗?
  • 【面试题】发起一次网络请求,当请求>=1s,立马中断
  • 微服务day07
  • 【图像压缩感知】论文阅读:Self-supervised Scalable Deep Compressed Sensing
  • 贪心算法入门(二)
  • RS®SZM 倍频器
  • 网优学习干货:2.6G仿真操作(2)
  • 信息安全--(四)网络安全体系与安全模型(二)
  • Linux系统安装nginx
  • 如何申请 Midjourney API ,看这篇文章就够了
  • Web自动化测试实战--博客系统
  • css中 display block属性的用法
  • docker里装mysql
  • 使用控制台与键盘进行输入输出
  • 服务器数据恢复—光纤共享存储互斥设置不当导致数据丢失的数据恢复案例
  • NC 二分查找-II
  • SQL 中 LIKE 和 REGEXP 的相同点与不同点解析
  • 关于前端布局的基础知识
  • AI绘画【Stable Diffusion】抽卡必备!时间管理大师Agent Scheduler插件,一键设置任务,让你的休息时间充分利用起来!
  • 如何判断请求是否为跨域请求?——详细教程
  • Godot vscode c# 调试方法
  • Linux——用户和权限
  • 代理 IP 在工业物联网中的大作用
  • 自然灾害预警系统的重要性
  • FPGA概述
  • 算法训练营|图论第7天 prim算法 kruskal算法