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

文章目录

  • 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.mfbz.cn/a/58338.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

程序员自由创业周记#5:加一上线

程序员自由创业周记#5:加一上线 这是一位程序员进行独立开发创业的记录,将分享创业过程中的所思所想以及收支明细。 充实 如果说程序员独立创业的成功率只有5%,那如果家里有一位3岁多还没上幼儿园的小朋友要照顾,成功的概率至少还…

rv1109/1126 rknn 模型部署过程

rv1109/1126是瑞芯微出的嵌入式AI芯片,带有npu, 可以用于嵌入式人工智能应用。算法工程师训练出的算法要部署到芯片上,需要经过模型转换和量化,下面记录一下整个过程。 量化环境 模型量化需要安装rk的工具包: rockchip-linux/rk…

【Spring】(一)Spring设计核心思想

文章目录 一、初识 Spring1.1 什么是 Spring1.2 什么是 容器1.3 什么是 IoC 二、对 IoC 的深入理解2.1 传统程序开发方式存在的问题2.2 控制反转式程序的开发2.3 对比总结 三、对 Spring IoC 的理解四、DI 的概念4.1 什么是 DI4.2 DI 与 IoC的关系 一、初识 Spring 1.1 什么是…

flutter:Future、Stream、RxDart

Future 在Flutter中,Future是Dart语言中的一个类,用于表示异步操作的结果。与Future相关的的重要关键字包括async和await。 async:这个关键字用于在方法或函数声明前添加,以指示该方法为异步方法。在异步方法中,执行…

c++画出分割图像,水平线和垂直线

1、pca 找到图像某个区域的垂直线&#xff0c;并画出来 // 1、 斑块的框 血管二值化图&#xff0c;pca 找到垂直血管壁的直线, 还是根据斑块找主轴方向吧// Step 1: 提取斑块左右范围内的血管像素点坐标&#xff0c;std::vector<cv::Point> points;for (int y 0; y <…

用Apache Echarts展示数据

目录 1.后端代码 1.1 实体类&#xff1a; 1.2 SQL语句&#xff1a; 2.前端代码 2.1 安装 Apach Echarts安装包&#xff1a; 2.2 查找数据并赋值给Echarts 思路&#xff1a;后端查到数据&#xff0c;包装为map&#xff0c;map里有日期和每日就诊人数&#xff0c;返回给前端…

异或运算详解

异或运算详解 定义特性用途总结 定义 参与运算的两个数据,按二进制位进行 ^ 运算,如果两个相对应为值相同结果为0,否则为1 1 ^ 0 1 0 ^ 1 1 0 ^ 0 0 1 ^ 1 0特性 异或^运算只能用于数值(整数) x ^ 0 x x ^ x 0用途 两个值交换,而不用使用临时变量 a a ^ b; b b ^…

css在线代码生成器

这里收集了许多有意思的css效果在线代码生成器适合每一位前端开发者 布局&#xff0c;效果类&#xff1a; 网格生成器https://cssgrid-generator.netlify.app/ CSS Grid Generator可帮助开发人员使用CSS Grid创建复杂的网格布局。网格布局是创建Web页面的灵活和响应式设计的强…

【Linux】在服务器上创建Crontab(定时任务),自动执行shell脚本

业务场景&#xff1a;该文即为上次编写shell脚本的姊妹篇,在上文基础上,将可执行的脚本通过linux的定时任务自动执行,节省人力物力,话不多说,开始操作! 一、打开我们的服务器连接工具 连上服务器后,在任意位置都可以执行:crontab -e 如果没有进入编辑cron任务模式 根据提示查看…

Day01-作业(HTMLCSS)

作业1&#xff1a;通过HTML的标签及CSS样式&#xff0c;完成如下企业简介html页面的制作 A. 最终效果如下&#xff1a; B. 文字素材如下&#xff1a; 企业简介传智教育(股票代码 003032)&#xff0c;隶属江苏传智播客教育科技股份有限公司&#xff0c;注册资本4亿元&#xff0…

国产GOWIN实现低成本实现CSI MIPI转换DVP

CSI MIPI转换DVP&#xff0c;要么就是通用IC操作&#xff0c;如龙讯芯片和索尼芯片&#xff0c;但是复杂的寄存器控制器实在开发太累。对于FPGA操作&#xff0c;大部分都是用xilinx的方案&#xff0c;xilinx方案成本太高&#xff0c;IP复杂。 而用国产GOWIN已经实现了直接mipi …

腾讯云TencentOS Server镜像系统常见问题解答

腾讯云TencentOS Server镜像是腾讯云推出的Linux操作系统&#xff0c;完全兼容CentOS生态和操作方式&#xff0c;TencentOS Server操作系统为云上运行的应用程序提供稳定、安全和高性能的执行环境&#xff0c;TencentOS可以运行在腾讯云CVM全规格实例上&#xff0c;包括黑石物理…

jmeter之接口测试(http接口测试)

基础知识储备 一、了解jmeter接口测试请求接口的原理 客户端--发送一个请求动作--服务器响应--返回客户端 客户端--发送一个请求动作--jmeter代理服务器---服务器--jmeter代理服务器--服务器 二、了解基础接口知识&#xff1a; 1、什么是接口&#xff1a;前端与后台之间的…

【设计模式】单例模式

什么是单例模式&#xff1f; 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点 单例模式的应用场景 1.整个程序的运行中只允许有一个类的实例&#xff1b; 2.需要频繁实例化然后销毁的对象。 3.创建对象时耗时过多或者耗资源过多&#xff0c;但又经常用到…

Python web实战 | 使用 Flask 实现 Web Socket 聊天室

概要 今天我们学习如何使用 Python 实现 Web Socket&#xff0c;并实现一个实时聊天室的功能。本文的技术栈包括 Python、Flask、Socket.IO 和 HTML/CSS/JavaScript。 什么是 Web Socket&#xff1f; Web Socket 是一种在单个 TCP 连接上进行全双工通信的协议。它是 HTML5 中的…

Flutter Flar动画实战

在Flare动面出现之前,Flare动画大体可以分为使用AnimationController控制的基础动画以及使用Hero的转场动画,如果遇到一些复杂的场景,使用这些动画方案实现起来还是有难度的。不过,随着Flutter开始支持Flare矢量动面,Flutter的动画开发也变得越来越简单。事实上,Flare动画…

2024考研408-计算机网络 第三章-数据链路层学习笔记

文章目录 前言一、数据链路层的功能1.1、数据链路层的研究思想1.2、数据链路层基本概念1.3、数据链路层功能概述&#xff08;5个功能&#xff09; 二 、组帧2.1、封装成帧以及发送帧的过程&#xff08;包含名词解释&#xff09;2.2、实现透明传输及四种组帧方法2.2.1、什么是透…

为什么马斯克和奥特曼都想重振加密货币?

1、前言 加密货币已经死了吗&#xff1f;这个问题的答案取决于谁来回答。一个加密爱好者会给你一百个不同的理由来解释为什么加密货币没有死。特斯拉CEO埃隆马斯克和OpenAI CEO 山姆奥特曼都对加密货币及其在塑造未来世界中的潜在作用有着浓厚的兴趣。 在过去很长一段时间里&…

涛思数据与拾贝云达成战略合作,携手赋能工业数字化转型

2023 年 7 月 27 日&#xff0c;北京涛思数据科技有限公司&#xff08;以下简称“涛思数据”&#xff09;与广州拾贝云科技有限公司&#xff08;以下简称“拾贝云”&#xff09;于广州签署战略合作协议。双方围绕电力行业的需求与痛点展开积极讨论&#xff0c;就如何量身打造最…

ZKML——EZKL团队分享

1. 引言 “ZKP之于数字签名” 类似于 “以太坊之于比特币”&#xff1a; 所谓数字签名&#xff0c;是指&#xff1a;“我知道某秘密secrets&#xff0c;使得 F(secrets, public inputs)pubic outputs”&#xff0c;其中F为fixed function&#xff08;固定函数&#xff09;。这…