《OpenCV 中阈值处理方法全解析及应用实例》

devtools/2024/11/25 3:03:35/

在这里插入图片描述

简介:本文详细介绍了 OpenCV 中多种阈值处理方法,包括cv2.threshold函数相关的二值化、反二值化、截断化、超阈值零处理、低阈值零处理等阈值处理方式,解析了阈值分割的作用以及函数返回阈值的原因。同时还涵盖了自适应阈值处理和 Otsu 阈值处理,通过多个实际代码案例展示了不同阈值处理方法在图像上的应用效果对比,帮助读者深入理解并掌握这些阈值处理技术在图像处理中的运用,便于根据实际需求选择合适的阈值处理手段。
如果你觉得我的文章对你有所帮助,希望你点赞收藏关注,持续学习OpenCV 相关的知识

这里写目录标题

  • 1 threshold函数
    • 1.1语法
    • 1.2为什么要进行阈值分割
    • 1.3解析为什么要返回阈值
    • 1.4 二值化阈值处理(cv2.THRESH_BINARY)
    • 1.5 反二值化阈值处理(cv2.THRESH_BINARY_INV)
    • 1.6 截断化阈值处理
    • 1.7 超阈值零处理(cv2.THRESH_TOZERO_INV)与低阈值零处理(cv2.THRESH_TOZERO)
  • 2 自适应阈值处理
  • 3 Otsu阈值处理
  • 致谢

1 threshold函数

1.1语法

line返回的阈值 , image = cv2.threshold(要进行阈值分割的图像src,要设定的阈值thresh,阈值分割的类型type,当type为THRESH_BINARY或者THRESH_BINARY_INV类型时,需要设定 的最大值maxval)

1.2为什么要进行阈值分割

作用有很多,这里讲两个:

  1. 减少数据量:一幅图像通常包含大量的像素信息。阈值分割可以将图像简化为二值图像(只有 0 和 1 两种像素值,分别代表背景和目标)。这样可以大大减少后续处理的数据量。例如,对于一个包含大量细节的自然场景图像,如果只关注图像中的主要物体轮廓,通过阈值分割将物体和背景分离,得到的二值图像可以在存储和处理时占用更少的资源。
  2. 形状分析:对于形状分析,阈值分割是第一步。将目标物体分割出来后,可以更好地计算物体的形状参数,如周长、面积、圆形度等。例如,在机械零件的形状检测中,先通过阈值分割得到零件的轮廓,然后分析其形状是否符合设计标准。

1.3解析为什么要返回阈值

学习,千万不能知其然,而不知其所以然,不能混日子.做事要用心,不能应付,多想想为什么。要想明白,多思考,对于这个函数:
line返回的阈值 , image = cv2.threshold(要进行阈值分割的图像src,要设定的阈值thresh,阈值分割的类型type,当type为THRESH_BINARY或者THRESH_BINARY_INV类型时,需要设定 的最大值maxval)
为什么要使用line接收他的阈值作为返回值呢?明明我们已经传入了阈值参数。所以我就十分好奇,去搜索了一番原因,有这么几条:

  1. 在自适应阈值分割中,你传入的初始阈值可能只是一个参考或者根本不被使用。函数会根据图像的局部特征(如局部均值、局部高斯加权均值等)来计算每个像素位置合适的阈值。在这种情况下,返回的阈值可以让你了解函数实际使用的阈值是多少。例如,在处理光照不均匀的图像时,自适应阈值分割会根据图像不同区域的亮度自动调整阈值。返回的阈值可以帮助你分析这些调整后的阈值是否合理,是否符合图像的实际情况。
  2. 即使你传入了一个固定的阈值,返回这个阈值也有好处。在进行多次阈值分割实验或者在一个处理流程中需要记录阈值信息时,你可以方便地获取并存储这个阈值。假设你正在尝试不同的阈值来优化目标提取的效果,返回的阈值可以让你记录每次使用的阈值和对应的分割结果,以便后续比较和分析,找到最佳的阈值设置。
  3. 这个返回的阈值可以作为其他函数的输入或者参考。例如,在一些高级的图像处理算法中,可能会根据阈值分割得到的阈值进一步调整图像的其他参数。或者在图像质量评估模块中,返回的阈值可以作为评估阈值分割效果的一个参考因素,帮助判断阈值是否合适,是否导致了过度分割或者分割不足的情况。

1.4 二值化阈值处理(cv2.THRESH_BINARY)

line返回的阈值 , image = cv2.threshold(要进行阈值分割的图像src,要设定的阈值thresh,阈值分割的类型type,当type为THRESH_BINARY或者THRESH_BINARY_INV类型时,需要设定 的最大值maxval)
顾名思义,二值化阈值处理type = cv2.THRESH_BINARY,就是把大于阈值的像素点统统设置为最大值maxval
这是我们文件夹的结构(我用的是jupyter notebooks,你们用pycharm也是一样的,都把图片文件和代码放在同一个文件夹下就可以了)
在这里插入图片描述

我是要把这个名字为pig.jpg的图片进行二值化阈值处理

import numpy as np
import cv2
red_pig = cv2.imread("pig.jpg",0)
line , bin_image = cv2.threshold(src = red_pig , thresh = 127 ,type = cv2.THRESH_BINARY,maxval = 255)
cv2.imshow("original",red_pig)
cv2.imshow("binary",bin_image)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
我们可以观察到一些灰度值小于等于阈值的点变成了0纯白色,其他的变成了255黑色

1.5 反二值化阈值处理(cv2.THRESH_BINARY_INV)

他是跟二值化阈值处理相反的,凡是大于阈值的都被处理为0白色,小于等于阈值的被处理为黑色,在下面这代码中,同时展现了二值化与反二值化给大家看:

import numpy as np
import cv2
red_pig = cv2.imread("pig.jpg",0)
line , bin_image = cv2.threshold(src = red_pig , thresh = 127 ,type = cv2.THRESH_BINARY,maxval = 255)
line_inv , bin_image_inv = cv2.threshold(src = red_pig , thresh = 127 ,type = cv2.THRESH_BINARY_INV,maxval = 255)
cv2.imshow("original",red_pig)
cv2.imshow("binary",bin_image)
cv2.imshow("INV_bin",bin_image_inv)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
从左往右第二张图和第三张图恰好是相反的,前者黑的后者是白的,前者白的后者是黑的

1.6 截断化阈值处理

大于阈值的被处理为阈值,小于阈值的不变

import numpy as np
import cv2
red_pig = cv2.imread("pig.jpg",0)
line ,trunc_image = cv2.threshold(src = red_pig,thresh =127,maxval = 255,type = cv2.THRESH_TRUNC)
print(trunc_image)

在这里插入图片描述

1.7 超阈值零处理(cv2.THRESH_TOZERO_INV)与低阈值零处理(cv2.THRESH_TOZERO)

超阈值零处理就是把大于阈值的部分按0处理,小于阈值的部分不变
低阈值零处理就是把小于阈值的部分按0处理,大于阈值的部分不变。
下面这个案例对pig.jpg这张图片分别进行两种零处理,比对效果差别:

import numpy as np
import cv2
red_pig = cv2.imread("pig.jpg",0)
line , ZERO_image = cv2.threshold(src = red_pig , thresh = 127 ,type = cv2.THRESH_TOZERO,maxval = 255)
line_inv , ZERO_image_inv = cv2.threshold(src = red_pig , thresh = 127 ,type = cv2.THRESH_TOZERO_INV,maxval = 255)
cv2.imshow("original",red_pig)
cv2.imshow("ZERO",ZERO_image)
cv2.imshow("INV_ZERO",ZERO_image_inv)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

2 自适应阈值处理

自适应阈值处理,适合处理一些明暗差异较大的图像,手动设置阈值不好设置,所以使用自适应比较方便
功能是根据邻域的加权平均值生成阈值
,先讲语法:
adapt_image 阈值处理后的图像 = cv2.adaptiveThreshole(原始图像src,maxValue最大值,adaptiveMethod代表自适应方法(包括均值和高斯两种),阈值处理方式(只能选cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV,邻域大小blocksize))

我们将在下面的案例中用
我从网上找了一张明暗差异较大的图像,起名black_and_white.JPG存入我的文件夹下:
在这里插入图片描述
在这里插入图片描述
在下面这段代码中展示普通阈值处理 与两种自适应阈值处理的效果差别:

import numpy as np
import cv2
black_white = cv2.imread("black_and_white.JPG",0)
line , bin_image = cv2.threshold(black_white,127,255,cv2.THRESH_BINARY)
Mean = cv2.adaptiveThreshold(black_white,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,5,3)
Gaussian = cv2.adaptiveThreshold(black_white,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,5,3)
cv2.imshow("original",black_white)
cv2.imshow("bin",bin_image)
cv2.imshow("mena",Mean)
cv2.imshow("Gauss",Gaussian)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
我们可以看到自适应阈值处理的效果明显由于普通的阈值处理

3 Otsu阈值处理

在普通的阈值处理的type加一个参数+cv2.THRESH_OTSU
他就可以自己遍历,找最合适的阈值
请看下面这段代码实例,还用black_and_white.JPG图片做案例:

import numpy as np
import cv2
black_white = cv2.imread("black_and_white.JPG",0)
line , bin_image = cv2.threshold(black_white,127,255,cv2.THRESH_BINARY)
line_otsu,otsu_bin = cv2.threshold(black_white,127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow("original",black_white)
cv2.imshow("bin",bin_image)
cv2.imshow("otsu",otsu_bin)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
通过结果可以看出来otsu明显获得了更多的轮廓信息

致谢

本文参考了一些博主的文章,博取了他们的长处,也结合了我的一些经验,对他们表达诚挚的感谢,使我对阈值处理 的使用有更深入的了解,也推荐大家去阅读一下他们的文章。纸上学来终觉浅,明知此事要躬行:
9.3Otsu阈值分割
OpenCV阈值处理(threshold函数、自适应阈值处理、Otsu处理)


http://www.ppmy.cn/devtools/136724.html

相关文章

sqlite-vec一个SQLite3高效向量搜索扩展--JDBC环境使用

最近要用SQLite3,之前放出来了SQLiteUtile工具,方便操作。今天发现AIGC方面,RAG知识库需要使用向量数据库,来存储知识信息。一般呢都是用mysql,但无奈的是mysql就是不让用。突然又发现SQLite3有向量库扩展组件&#xf…

HarmonyOS4+NEXT星河版入门与项目实战(11)------Button组件

文章目录 1、控件图解2、案例实现1、代码实现2、代码解释3、运行效果4、总结1、控件图解 这里我们用一张完整的图来汇整 Button 的用法格式、属性和事件,如下所示: 按钮默认类型就是胶囊类型。 2、案例实现 这里我们实现一个根据放大和缩小按钮来改变图片大小的功能。 功…

linux安装NVM与Node

linux安装NVM与Node 1.安装nvm 安装版本管理工具git:yum install git 查看git版本:git --version 开放443端口:sudo firewall-cmd --permanent --add-port443/tcp 重启防火墙:sudo firewall-cmd --reload 一键式安装指令&#…

pytorch自定义算子导出onnx

文章目录 1、为什么要自定义算子?2、如何自定义算子3、自定义算子导出onnx4、example1、重写一个pytorch 自定义算子(实现自定义激活函数)2、现有算子上封装pytorch 自定义算子(实现动态放大超分辨率模型) 1、为什么要…

计算机网络:概述知识点及习题练习

网课资源: 湖科大教书匠 1、因特网 网络之间需要路由器进行互联,互联网是网络的网络,因特网是最大的互联网,连接到网络的设备称为主机,一般不叫路由器为主机。 因特网发展:ARPNET->三级结构因特网&am…

项目学习:仿b站的视频网站项目03-注册功能

概括 通过上一期,完成了项目和数据库的基础结构的搭建,接下来主要是完成项目的注册功能。该功能模块主要分为有两个接口,一个是验证码接口,一个是注册接口。 让我们开始吧! 验证码接口 验证码的生成主要配合下面这…

Python自动化测试实践中pytest用到的功能dependency和parametrize

Python自动化测试中pytest用到的功能 1、pytest之@pytest.mark.dependency装饰器设置测试用例之间的依赖关系 1.1说明: 1、这是一个pytest第三方插件,主要解决用例之间的依赖关系。如果依赖的上下文测试用例失败后续的用例会被标识为跳过执行,相当于执行了 pytest.mark.s…

#渗透测试#红蓝攻防#HW#SRC漏洞挖掘01之静态页面渗透

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停…