opencv之阈值处理

2024-09-01 06:44
文章标签 opencv 阈值 处理

本文主要是介绍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 cv2def adaptive_threshold(image, block_size, C):rows, cols = image.shapepadded_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 - Cresult[i, j] = 255 if image[i, j] >= threshold else 0return 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 阈值法是一种自动选择阈值的全局方法,适合灰度直方图呈双峰分布的图像。

这篇关于opencv之阈值处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1126235

相关文章

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

Thymeleaf:生成静态文件及异常处理java.lang.NoClassDefFoundError: ognl/PropertyAccessor

我们需要引入包: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>sp

jenkins 插件执行shell命令时,提示“Command not found”处理方法

首先提示找不到“Command not found,可能我们第一反应是查看目标机器是否已支持该命令,不过如果相信能找到这里来的朋友估计遇到的跟我一样,其实目标机器是没有问题的通过一些远程工具执行shell命令是可以执行。奇怪的就是通过jenkinsSSH插件无法执行,经一番折腾各种搜索发现是jenkins没有加载/etc/profile导致。 【解决办法】: 需要在jenkins调用shell脚

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

树莓派5_opencv笔记27:Opencv录制视频(无声音)

今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi)  本人所用树莓派5 装载的系统与版本如下:  版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今天就水一篇文章,用树莓派摄像头,Opencv录制一段视频保存在指定目录... 文章提供测试代码讲解,整体代码贴出、测试效果图 目录 阶段一:录制一段

Verybot之OpenCV应用三:色标跟踪

下面的这个应用主要完成的是Verybot跟踪色标的功能,识别部分还是居于OpenCV编写,色标跟踪一般需要将图像的颜色模式进行转换,将RGB转换为HSV,因为对HSV格式下的图像进行识别时受光线的影响比较小,但是也有采用RGB模式来进行识别的情况,这种情况一般光线条件比较固定,背景跟识别物在颜色上很容易区分出来。         下面这个程序的流程大致是这样的: