【Opencv入门到项目实战】(二):图像阈值与平滑处理

news2024/12/28 4:13:11

文章目录

  • 1.图像阈值处理
    • 1.1简单阈值处理(Simple Thresholding)
    • 1.2自适应阈值处理(Adaptive Thresholding)
    • 1.3Otsu's阈值处理
  • 2.平滑处理
    • 1.1均值滤波(Mean Filter)
    • 1.2高斯滤波(Gaussian Filter)
    • 1.3中值滤波(Median Filter)

1.图像阈值处理

在图像处理中,阈值处理是一种常用的技术,可以将图像转换为二值图像,即只有两个像素值(一般为黑色和白色)。OpenCV提供了多种图像阈值处理的方法,接下来我们讨论一下在opencv如何对一个图形进行阈值处理。

1.1简单阈值处理(Simple Thresholding)

简单阈值处理是一种基本的阈值处理方法,它将图像的每个像素与一个阈值进行比较,并根据比较结果将像素设置为两个值中的一个。在OpenCV中,调用cv2.threshold()来实现,主要包含4个参数: 第一个为输入图,第二个我们设定的阈值,一般为127,那么我们就以127为界进行判断,第三个参数是最大的一个可能值,一般情况下为255。主要就是第四个参数,表示我们要进行的阈值处理及判断条件。这里主要包含5种方法,具体如下

cv2.threshold(input, thresh, maxval, type)

  • input: 输入图,只能输入单通道图像,通常来说为灰度图
  • thresh: 阈值
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • type:二值化操作的类型,包含以下5种类型:
  • cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
    • cv2.THRESH_BINARY_INV THRESH_BINARY的相反操作
    • cv2.THRESH_TRUNC 大于阈值部分设为阈值,其余不变
    • cv2.THRESH_TOZERO 大于阈值部分不变,否则设为0
    • cv2.THRESH_TOZERO_INV THRESH_TOZERO的相反操作

通常情况下,在我们图像当中,越亮的地方值越大,以第一个为例,在这里越亮的地方,超过阈值部分,我取255,是不是相当于把它放到极亮,相当于就是一个白点。否则的话就取零,因此比较暗的地方,小于阈值时我们就直接给它取零,相当于是一个黑的地方。接下来我们来看看这几种阈值处理的效果

首先导入一张灰度图

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline 
 
img=cv2.imread('yangqi.jpg') #导入你要读取的图片路径
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #灰度图读取
img_gray.shape
(238, 218)

可以看到此时的通道数为1

# 其中ret返回的是阈值
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) #超过127的取值为255,否则为0
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)#超过127的取值为0,否则为255
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)#超过阈值的设为阈值,否则不变
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)#超过127的不变,否则为0
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)#超过127的为0,否则不变

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

image-20230801132944181

第一幅图:原始的图像就是这只小狗,可以看出身体比较白,其余地方比较暗。

第二幅图:使用BINARY二值法处理的结果,处理完之后大于127亮点的全为白,暗点的全为黑,这个意思这是咱们第一种方法。

**第三幅图:**使用BINARYINV处理的结果,这和我们第二幅图的结果完全相反,处理完之后大于127亮点的全为黑,暗点的全为白

**第四幅图:**使用TRUNC截断值处理的结果,这个比较好理解,所有大于127截断使其等于127了,其余的不变

**第五幅图:**使用TOZERO,从名字上就可以理解它的用法,大于阈值的部分保持不变,小于阈值的部分变为0

**第六幅图:**使用TOZERO_INV,和上一种方法的结果刚好相反,大于阈值的变为0,小于阈值的保持不变。

1.2自适应阈值处理(Adaptive Thresholding)

自适应阈值处理是一种根据图像局部区域的特性自动确定阈值的方法。它将图像分成若干个小区域,并根据每个区域内像素的统计信息来计算阈值。在OpenCV中,可以使用cv2.adaptiveThreshold()函数来实现自适应阈值处理,具体语法如下

cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

参数说明:

  • src:输入的灰度图像,单通道图像。
  • maxValue:当像素超过阈值时,所设置的最大像素值。
  • adaptiveMethod:自适应方法的类型。可以是以下两种之一:
    • cv2.ADAPTIVE_THRESH_MEAN_C:根据邻域块的均值计算阈值。
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:根据邻域块的加权和的高斯平均值计算阈值。
  • thresholdType:阈值处理的类型。可以是以下两种之一:
    • cv2.THRESH_BINARY:超过阈值的像素被设置为 maxValue,否则设置为0。
    • cv2.THRESH_BINARY_INV:超过阈值的像素被设置为0,否则设置为 maxValue
  • blockSize:用于计算阈值的像素邻域大小。它必须是奇数,并且大于1。
  • C:在计算阈值时的常数,用于对均值或加权和进行调整。

函数的返回值是处理后的二值图像。

thresh1 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,3) #这里领域大小为3
thresh2 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY_INV,3,3)#这里领域大小为3

titles = ['Original Image', 'BINARY', 'BINARY_INV']
images = [img_gray, thresh1, thresh2]

for i in range(3):
    plt.subplot(1,3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

image-20230801174226641

通过自适应阈值处理,我们可以根据每个像素邻域内的统计信息来确定阈值,从而更好地适应不同区域之间的光照变化。这对于处理具有不均匀光照条件的图像非常有用,例如图像中存在阴影或光源不均匀的情况。

1.3Otsu’s阈值处理

Otsu's阈值处理是一种自动确定阈值的方法,它能够找到一个最佳的阈值,使得将图像分割为两个类别后的类别间方差最小化, 这种方法对于没有先验知识的图像分割非常有用。在OpenCV中,我们调用cv2.threshold()函数,并将阈值类型设置为cv2.THRESH_OTSU来实现Otsu's阈值处理。

ret, thresh = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

titles = ['Original Image', "Otsu's"]
images = [img_gray, thresh]

for i in range(2):
    plt.subplot(1,2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

ret 是计算得到的最佳阈值,thresh 是通过应用 Otsu's 方法得到的二值图像。

image-20230801174555870

ret
119.0

可以看到,Otsu's方法会自动计算阈值,这里阈值等于119,并将图像分为两个类别(黑色和白色)。

使用 Otsu's 阈值处理,我们无需手动选择阈值,而是通过计算来确定最佳阈值,从而实现更准确的图像分割。这对于具有不同光照条件、对比度变化或噪声存在的图像尤其有用。

2.平滑处理

当我们处理图像时,有时候需要对图像进行平滑处理,以减少噪声、去除细节或者模糊图像,它的具体计算有点类似卷积的计算,在介绍具体方法之前我们先来看一张图片:

img = cv2.imread('lenaNoise.png')
cv2.imshow('Noise', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

image-20230801170417971

可以看到这张图片上面有很多椒盐噪声,我们希望能够用平滑方法来处理,在OpenCV提供了多种图形平滑处理方法,下面我们详细介绍一些常用的方法:

1.1均值滤波(Mean Filter)

将每个像素的邻域像素的平均值作为该像素的新值。这种滤波器对于去除轻度噪声非常有效,但可能会导致图像变得模糊。在OpenCV中,我们调用cv2.blur()函数来实现均值滤波。

blur = cv2.blur(img, (3, 3)) #使用3×3的滤波器
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()

image-20230801170714356

可以看见上面的椒盐噪声减弱了一些,没有那么明显,下面我们来看一下它的具体计算逻辑,这里我们选择了3×3的滤波器,因此,每次我们都会看以目标像素为中心的3×3的领域9个值,如下图所示,以204为中心,我们计算包括它在内及其领域共9个值的平均值来做代替。

image-20230801171331324

1.2高斯滤波(Gaussian Filter)

刚刚我们介绍的均值平衡是简单的求算数平均,而高斯平衡认为其邻域像素的权重不应该一样,越靠近中心的像素权重应该越重,且权重服从高斯分布,然后使用高斯权重来计算邻域像素的加权平均值。相比于均值滤波器,高斯滤波器能够更好地保留图像的细节信息。在OpenCV中,可以使用cv2.GaussianBlur()函数来实现高斯滤波。

# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
gaussian = cv2.GaussianBlur(img, (3,3), 1)  

cv2.imshow('gaussian', gaussian)
cv2.waitKey(0)
cv2.destroyAllWindows()

image-20230801171821984

1.3中值滤波(Median Filter)

中值滤波是一种非线性滤波器,它将每个像素的邻域像素的中值作为该像素的新值。这种滤波器对于去除椒盐噪声非常有效,同时能够保留图像边缘的细节,对于我们给出的这张图而言,效果非常好。在OpenCV中,我们调用cv2.medianBlur()函数来实现中值滤波。

# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 3)  # 中值滤波

cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()

image-20230801171936838

可以看出使用中值平滑处理后的效果针对于椒盐噪声非常好。下面我们将三个图放一起来比较

# 展示所有的
res = np.hstack((blur,gaussian,median))#按水平方向堆砌,三张图水平方向放一起

cv2.imshow('blur vs gaussian vs median', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

image-20230801172111786

上述几种方法究竟选哪一个好呢?一般我们需要根据特定的任务和图像特征进行评估和调整,根据我们的需求和图像特点,选择合适的方法来实现图像的平滑处理,例如以本案例来说,使用中值平滑处理的效果是最好的。

🔎本章的介绍到此介绍,如果文章对你有帮助,请多多点赞、收藏、评论、订阅支持!!《Opencv入门到项目实战》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/835240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA纯verilog实现Gzip数据压缩deflate算法,提供工程源码和技术支持

目录 1、前言2、我这儿已有的FPGA压缩算法方案3、FPGA Gzip数据压缩功能和性能4、FPGA Gzip数据压缩设计方案输入输出接口描述数据处理流程LZ77压缩器哈夫曼编码输出缓存 数据输出说明特殊说明 5、vivado仿真6、vivado工程7、上板调试验证FPGA开发板测试本zip算法对比于评估 8、…

【JDK版本差异】Optional.requireNonNullElseGet在JAVA8中的替代表述

Objects.requireNonNullElseGet 是 Java 9 引入的方法,不在 Java 8 中可用。但是, 可以使用 Java 8 的一些功能来模拟类似的效果。 快速查阅 JDK9以上表述: this.principalFactory Objects.requireNonNullElseGet(principalFactory, Defau…

如何测出 Scratch 的指令反应时间

相信看了标题,你一定会很吃惊,你会觉得scratch不是没有反应时间吗? 但其实不是,这也是我偶然间发现的,这期的内容较少,对你的技术涨幅很小,但可以当作娱乐来看 其实就7个代码,但看着…

(自控原理)线性系统的时域分析法

目录 一、系统时间响应的性能指标 1、典型输入信号 2、动态性能与稳态性能 二、一阶系统的时域分析 1、一阶系统的数学模型 2、一阶系统的单位阶跃响应 三、二阶系统的时域分析 1、二阶系统的数学模型 2、二阶系统的单位阶跃响应 3、欠阻尼二阶系统的动态过程分析 4…

redis原理 5:同舟共济 —— 事务

为了确保连续多个操作的原子性,一个成熟的数据库通常都会有事务支持,Redis 也不例外。Redis 的事务使用非常简单,不同于关系数据库,我们无须理解那么多复杂的事务模型,就可以直接使用。不过也正是因为这种简单性&#…

国内版ChatGPT平替

想体验的朋友可以去微信搜索小程序 “ robot buddy ”

2024年杭州电子科技大学MEM项目招生信息全面了解

2024年全国管理类硕士联考备考已经到了最火热的阶段,不少考生开始持续将注意力集中在备考的规划中!杭州达立易考教育整合浙江省内的MEM目信息,为大家详细梳理了相关报考参考内容,方便大家更好完成择校以及针对性的备考工作。本期为…

【Spring Boot】Thymeleaf模板引擎 — Thymeleaf表达式

Thymeleaf表达式 本节介绍Thymeleaf的各种表达式&#xff0c;通过一些简单的例子来演示Thymeleaf的表达式及用法。 1.变量表达式 变量表达式即获取后台变量的表达式。使用${}获取变量的值&#xff0c;例如&#xff1a; <p th:text"${name}">hello</p>…

Windows Server 2012 R2 安装 Oracle RAC 11g R2

Windows Server 2012 R2 安装 Oracle RAC 11g R2 环境准备安装系统设置虚拟网络配置虚拟机网卡开机进行系统配置关闭防火墙设置网络系统高级设置修改注册表修改计算机名称设置账户控制RAC1 和 RAC2 的磁盘共享修改 hosts同步时间在 RAC1 RAC2 DATA 中安装 .net3.5在 DATA 中搭建…

windows下redis的下载和安装

文章目录 1 下载2 打开解压文件&#xff0c;可以看到以下内容3 使用命令进行安装和注册redis到window服务4 查看服务 1 下载 https://github.com/MicrosoftArchive/redis/releases 2 打开解压文件&#xff0c;可以看到以下内容 3 使用命令进行安装和注册redis到window服务 …

一文学透设计模式——抽象工厂模式

创建者模式 抽象工厂模式 概念 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这是很多地方对于抽象工厂模式的描述&#xff0c;说实话感觉不是特别好懂。…

ResNet-残差网络一

文章目录 残差网络深度网络退化残差结构残差网络对比测试plain net VS residual net不同的shrotcut connection残差网络增加层数 著名的残差网络主要是在两片论文里提出&#xff1a; Deep Residual Learning for Image RecognitionIdentity Mappings in Deep Residual Networks…

yolov8在rknn(rv1109/1126)模型转换、量化移植过程

续&#xff1a;rv1109/1126 rknn 模型量化过程_CodingInCV的博客-CSDN博客 Yolov8简介 yolov8是比较新的目标检测模型&#xff0c;根据论文和开源项目的报告&#xff0c;相对使用比较广泛的yolov5提升还比较明显。 yolov8与yolov5相比&#xff0c;结构上的主要区别是将C3结构…

hutool Sm2加解密-自定义公钥私钥

代码 首先说结论&#xff0c;hutool 的SM2对象的公钥私钥是不关联的&#xff0c;你可以存自己的私钥和别人的公钥&#xff0c;这样解密的时候只要协商好就能用了&#xff0c;以下是调换公钥私钥的加解密案例 公钥格式 04公钥x公钥y //使用自定义的公钥私钥生成sm2Testpubli…

android资深工程师如何分析system_server异常

Android系统中的System Server负责管理许多关键功能&#xff0c;例如进程管理、电源管理等。如果System Server出现异常&#xff0c;可能会导致系统重启或部份功能失效。作为Android资深工程师&#xff0c;分析System Server的异常状况时&#xff0c;考虑以下步骤&#xff1a;查…

晶澳转债上市价格预测

晶澳转债 基本信息 转债名称&#xff1a;晶澳转债&#xff0c;评级&#xff1a;AA&#xff0c;发行规模&#xff1a;89.603077亿元。 正股名称&#xff1a;晶澳科技&#xff0c;今日收盘价&#xff1a;31.71元&#xff0c;转股价格&#xff1a;38.78元。 当前转股价值 转债面值…

我做了一个JPA Specification的优化

目录 一、参考二、概述流程效果感受 三、实现原理AST树结构AstNode主要结构 把表达式解析成AstAst 解析成 JPA Specification 三、项目地址四、目前阶段的总结 一、参考 如何搞一个支持自定义函数和变量的四则运算的抽象语法树出来 二、概述 这是一个可以优化生成Specificati…

Android SystemServer中Service的创建和启动方式(基于Android13)

Android SystemServer创建和启动方式(基于Android13) SystemServer 简介 Android System Server是Android框架的核心组件&#xff0c;运行在system_server进程中&#xff0c;拥有system权限。它在Android系统中扮演重要角色&#xff0c;提供服务管理和通信。 system …

Pycharm中修改注释文本的颜色(详细设置步骤)

下面是在Pycharm中设置注释文本颜色的详细步骤&#xff1a; 下面是修改前后对比&#xff1a; 修改前注释行的颜色&#xff1a; 修改后注释行的颜色&#xff1a; 以上就是Pycharm中修改注释文本颜色的详细步骤&#xff0c;希望能帮到你&#xff01;

pve安装dsm7.2,并启用照片同步

目录 1.文件准备 2. 创建虚拟机 3. 编译引导文件 4. 群晖安装 5. 安装Photos和mmfpeg 6. 安装手机APP 之前安装了pve版本的dsm6.2了&#xff0c;近期换硬盘&#xff0c;加上对dsm6.2的moments性能实在不满意&#xff0c;就产生尝鲜的想法&#xff0c;因为dsm7.0发布很久了…