opencv之图像亮度变换和形态学变换(八)

opencv之图像亮度变换和形态学变换(八)

文章目录

  • opencv之图像亮度变换和形态学变换(八)
  • 一、图像亮度变换
    • 1.1 亮度变换
    • 1.2 线性变换
    • 1.3 直接像素值修改
    • 案例
  • 二、形态学变换
    • 2.1 核
    • **2.2 腐蚀(Erosion)**
    • **2.3 膨胀(Dilation)**
    • **2.4 开运算(Opening)**
    • **2.5 闭运算(Closing)**
    • **2.6 礼帽运算(Top Hat)**
    • **2.7 黑帽运算(Black Hat)**
    • **2.8 形态学梯度(Morphological Gradient)**
    • **核心总结**
    • 案例


一、图像亮度变换

1.1 亮度变换

在讲解亮度时,需要和对比度一起来进行解释。

对比度调整:图像暗处像素强度变低,图像亮处像素强度变高,从而拉大中间某个区域范围的显示精度。

亮度调整:图像像素强度整体变高或者变低。

在这里插入图片描述
上图中,(a)把亮度调高,就是图片中的所有像素值加上了一个固定值;(b)把亮度调低,就是图片中的所有像素值减去了一个固定值;©增大像素对比度(白的地方更白,黑的地方更黑);(d)减小像素对比度(整幅图都趋于一个颜色);

OpenCV调整图像对比度和亮度时,公式为: g ( i , j ) = α f ( i , j ) + β g(i,j)=\alpha f(i,j)+\beta g(i,j)=αf(i,j)+β。但是不能浅显的讲 α \alpha α是控制对比度, β \beta β是控制亮度的。

对比度:需要通过 α 、 β \alpha、\beta αβ一起控制。

亮度:通过 β \beta β控制。

1.2 线性变换

使用 cv2.addWeighted() 函数,可以对图像的像素值进行加权平均,进而改变图像的整体亮度。亮度增益可以通过向每个像素值添加一个正值来实现。

cv2.addWeighted(src1, alpha, src2, beta, gamma)

  • src1:第一张输入图像,它将被赋予权重 alpha

  • alpha:第一个输入图像的权重。

  • src2:第二张输入图像,它将被赋予权重 beta

  • beta:第二个输入图像的权重。

  • gamma:一个标量,将被添加到权重求和的结果上,可用于调整总体亮度。

    计算公式为: dst = src1 * alpha + src2 * beta + gamma

1.3 直接像素值修改

如果只需要增加或减少固定的亮度值,可以直接遍历图像像素并对每个像素值进行加减操作。

使用的API:

numpy.clip(a, a_min, a_max)

用于对数组中的元素进行限定,将超出指定范围的元素值截断至指定的最小值和最大值之间

  • a:输入数组。

  • a_min:指定的最小值,数组中所有小于 a_min 的元素将被替换为 a_min

  • a_max:指定的最大值,数组中所有大于 a_max 的元素将被替换为 a_max

案例

案例一

import numpy as np
import cv2 as cvimg = cv.imread("images/1.jpg")
# 使用cv2.addWeihted(src1, alpha, src2, beta, gamma)实现线性变换
"""
np.zeros_like(img) 生成与img相同形状的零矩阵
np.ones_like(img) 生成与img相同形状的1矩阵
np.full_like(img, n) 生成与img相同形状的n矩阵
"""
dst = cv.addWeighted(img, 1, np.zeros_like(img), 0, 50)cv.imshow("dst", dst)
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例二

import cv2 as cv
import numpy as npwindow_name = 'Trackbar'
cv.namedWindow(window_name)# 写一个改变图像亮度的方法
def change(p):img = cv.imread('images/1.jpg')if img is None:print("图像加载失败,请检查路径!")return# 把滑条范围映射到-255~255p = int(p)  # 确保 p 是整数p = p / 255 * (255 - (-255)) - 255# 亮度变换dst = np.uint8(img + p)dst = np.clip(dst, 0, 255)cv.imshow(window_name, dst)# 创建滑条
cv.createTrackbar('p', 'Trackbar', 0, 255, change)# 初始化显示
change(0)  # 初始化时调用一次,确保图像显示cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

二、形态学变换

形态学变换(Morphological Transformations)是一种基于形状的简单变换,它的处理对象通常是二值化图像。形态学变换有两个输入,一个输出:输入为原图像、核(结构化元素),输出为形态学变换后的图像。其基本操作有腐蚀和膨胀,这两种操作是相反的,即较亮的像素会被腐蚀和膨胀。下面我们来说一下核、腐蚀与膨胀的概念。

2.1 核

自适应二值化中,我们已经接触过核了,还记得吗?就是那个在原图中不断滑动计算的3*3的小区域,那其实就是一个3*3的核。

核(kernel)其实就是一个小区域,通常为3*3、5*5、7*7大小,有着其自己的结构,比如矩形结构、椭圆结构、十字形结构,如下图所示。通过不同的结构可以对不同特征的图像进行形态学操作的处理。
在这里插入图片描述

2.2 腐蚀(Erosion)

  • 作用:收缩白色区域(前景),消除小噪点、细线
  • 原理:结构元素覆盖区域内有黑即黑(取最小值)
  • 效果:目标"变瘦",边缘平滑

2.3 膨胀(Dilation)

  • 作用:扩展白色区域,填补空洞、断裂
  • 原理:结构元素覆盖区域内有白即白(取最大值)
  • 效果:目标"变胖",轮廓连通

2.4 开运算(Opening)

  • 操作:先腐蚀后膨胀
  • 作用:消除孤立噪点、分离粘连物体
  • 特点:保留原主体,去除小干扰

2.5 闭运算(Closing)

  • 操作:先膨胀后腐蚀
  • 作用:填充内部孔洞、闭合缝隙
  • 特点:平滑轮廓,保持主体完整性

2.6 礼帽运算(Top Hat)

  • 公式:原图 - 开运算结果
  • 作用:提取比背景亮的细节(如微小亮斑)
  • 应用:背景均匀时的前景增强

2.7 黑帽运算(Black Hat)

  • 公式:闭运算结果 - 原图
  • 作用:提取比背景暗的细节(如暗色缺陷)
  • 应用:检测深色区域或空洞

2.8 形态学梯度(Morphological Gradient)

  • 公式:膨胀图 - 腐蚀图
  • 作用:突出边缘轮廓
  • 效果:类似边缘检测,但更平滑

核心总结

操作关键作用典型应用场景
腐蚀消除噪点、细化物体去除胡椒噪声
膨胀连接断裂、填充孔洞文字修复
开运算去噪+保形分离粘连细胞
闭运算补洞+平滑填充指纹断裂
礼帽提取亮细节显微图像亮斑提取
黑帽提取暗细节工业缺陷检测
形态学梯度边缘增强目标轮廓提取

:所有操作均依赖**结构元素(核)**的形状和大小选择!

案例

案例一:腐蚀和膨胀

import cv2 as cv
import numpy as nplong = cv.imread("images/long.png")
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 腐蚀操作cv.erode(src, kernel, dst, anchor, iterations, borderType, borderValue)
# iterations表示迭代次数
dst_erode = cv.erode(long,kernel,iterations=1)# 膨胀操作cv.dilate(src, kernel, dst, anchor, iterations, borderType, borderValue)
dst_dilate = cv.dilate(long,kernel,iterations=5)cv.imshow("long",long)
cv.imshow("dst_erode",dst_erode)
cv.imshow("dst_dilate",dst_dilate)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例二

import cv2 as cv
import numpy as npcar = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 开运算 cv.morphologyEx(src,op,kernel) # 先腐蚀再膨胀
open = cv.morphologyEx(car,cv.MORPH_OPEN,kernel)
# 闭运算 cv.morphologyEx(src,op,kernel) # 先膨胀再腐蚀
close = cv.morphologyEx(car,cv.MORPH_CLOSE,kernel)# 显示图像
cv.imshow("car",car)
cv.imshow("open",open)
cv.imshow("close",close)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例三

import cv2 as cv
import numpy as npcar = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 礼帽运算cv.morphologyEx(src,op,kernel) 原图减"开运算"
dst_top = cv.morphologyEx(car,cv.MORPH_TOPHAT,kernel)# 黑帽运算cv.morphologyEx(src,op,kernel) "闭运算"的结果图与原图像之差
dst_black = cv.morphologyEx(car,cv.MORPH_BLACKHAT,kernel)cv.imshow("car",car)
cv.imshow("dst_top",dst_top)
cv.imshow("dst_black",dst_black)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

案例四

import cv2 as cv
import numpy as npcar = cv.imread("images/car4.png")
car = cv.resize(car,(640,480))
# 定义一个5×5的卷积核
kernel = np.ones((5,5),np.uint8)
# 形态学梯度 cv2.morphologyEx(src,op,kernel) 像素点在膨胀后的图像值与其在腐蚀后的图像值之差
gradient = cv.morphologyEx(car,cv.MORPH_GRADIENT,kernel)
cv.imshow("gradient",gradient)
cv.imshow("car",car)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

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

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

相关文章

【初阶数据结构】树——二叉树——堆(中)

文章目录 前言 一、堆的概念与结构 二、堆的实现 堆的定义 1.初始化堆 2.堆的销毁 3.堆的插入 3.1向上调整算法 4.堆的判空 5.求有效个数 6.删除堆顶数据 6.1向下调整算法 7.获取栈顶数据 三、完整源码 总结 前言 上篇了解树和二叉树相关的概念,这篇学习一种特殊的…

AM剪辑软件汉化版:简单易用,开启视频创作之旅

在短视频流量时代,视频剪辑已经成为许多人表达自我和记录生活的重要方式。无论是分享日常点滴、制作创意视频还是进行专业内容创作,一款功能强大且操作简便的视频剪辑软件是必不可少的。今天,我们要介绍的 AM剪辑软件汉化版,就是这…

llfc项目分布式服务笔记

一、系统整体架构流程图(简明版) 复制代码 +---------------+ +------------------+ +----------------+ | 客户端 (Client) |--------->| GateServer |----------| StatusServer |<--+ +---------------+ +--------------…

C++如何设计和实现缓存(cache)来减少对后端存储的访问压力

随着数据量的激增和用户对低延迟、高吞吐量需求的不断提升,如何减少系统瓶颈、提升响应速度成为了开发者的核心挑战之一。在这一背景下,缓存(cache)作为一种关键的技术手段,逐渐成为解决性能问题的核心策略。缓存的本质是通过存储频繁访问的数据或计算结果,减少对后端存储…

华为设备端口隔离

端口隔离的理论与配置指南 一、端口隔离的理论 基本概念 端口隔离&#xff08;Port Isolation&#xff09;是一种在交换机上实现的安全功能&#xff0c;用于限制同一VLAN内指定端口间的二层通信。被隔离的端口之间无法直接通信&#xff0c;但可通过上行端口访问公共资源&#…

1688平台商品详情接口开发指南(含Python代码示例)

接口概述 1688开放平台提供的商品详情接口&#xff08;item_get&#xff09;是获取商品核心数据的重要API&#xff0c;开发者可通过该接口获取商品标题、价格、规格参数、图片等详细信息。本文重点解析标题字段的获取方式&#xff0c;并提供完整代码示例。 接口请求参数 基础…

Edge浏览器PDF字体显示错误

Edge浏览器PDF字体显示错误 软件版本信息 Edge Version: 136.0.3240.50 Word Version: Microsoft Office 专业增强版2021问题描述 在Word中使用多级列表自动编号, 并使用Word软件自带的导出为PDF文件功能, 在Word中显示正常的数字, 在Edge中查看PDF将会出现渲染错误的现象,…

Redis能保证数据不丢失吗之AOF

我们都知道,Redis是一个基于内存的k-v数据库,既然是基于内存的,那么Redis如何保证数据不丢失?以及真的能做到数据的百分百不丢失吗? 为什么Redis数据需要持久化机制? Redis的一个常用场景是缓存,通常缓存丢失的话,我们也可以从数据库中重新找回,那么为什么Redis还需…

Apache POI实现Excel的基本写入、导出操作

目录 一、Apache POI 简介 二、入门案例(写入导出) 三、实际开发过程中的导出操作——&#xff08;将文件下载至客户端浏览器中&#xff09; 一、Apache POI 简介 Apache POI&#xff08;Poor Obfuscation Implementation&#xff09;是 Apache 软件基金会的开源项目&#…

HTTP请求与前端资源未优化的系统性风险与高性能优化方案

目录 前言一、未合并静态资源&#xff1a;HTTP请求的隐形杀手1.1 多文件拆分的代价1.2 合并策略与工具链实践 二、未启用GZIP压缩&#xff1a;传输流量的浪费2.1 文本资源的压缩潜力2.2 服务端配置与压缩算法选择 三、未配置浏览器缓存&#xff1a;重复请求的根源3.1 缓存失效的…

AgentMesh开源多智能体 (Multi-Agent) 平台

AgentMesh 是一个开源的多智能体 (Multi-Agent) 平台&#xff0c;核心目标是解决多个智能体之间的通信和协同问题&#xff0c;真正实现 “11>2” 的效果。能够帮助用户快速创造自己的多智能体团队&#xff0c;或是让已有的多个单一智能体获得协同能力&#xff0c;最终解决更…

基于Jetson Nano与PyTorch的无人机实时目标跟踪系统搭建指南

引言&#xff1a;边缘计算赋能智能监控 在AIoT时代&#xff0c;将深度学习模型部署到嵌入式设备已成为行业刚需。本文将手把手指导读者在NVIDIA Jetson Nano&#xff08;4GB版本&#xff09;开发板上&#xff0c;构建基于YOLOv5SORT算法的实时目标跟踪系统&#xff0c;集成无人…

从入门到登峰-嵌入式Tracker定位算法全景之旅 Part 8 |产品化与运维:批量标定、误差监控、OTA 升级与安全防护

Part 8 |产品化与运维:批量标定、误差监控、OTA 升级与安全防护 本章聚焦将嵌入式 Tracker 定位系统推向 量产与运维 阶段,覆盖 批量标定、误差监控、远程 OTA 升级 以及 定位安全防护,确保产品在大规模部署后仍能稳定、精准、可靠地运行。 一、批量标定平台搭建 标定流程…

gsplat 渲染库 安装部署笔记

目录 Windows 安装 Nvdiffrast安装 gsplat安装成功笔记: cu118测试ok vs 编译安装报错: 安装命令: 报错结果: Windows 安装 pip install gsplat 安装成功,调用报错: python -c "from gsplat import csrc as _C" Traceback (most recent call last): …

Java二维码学习

使用Java语言生成二维码有以下方式,一是谷歌的zxing,二是基于zxing实现的qrcode开源项目,三是基于zxing实现的qrgen开源项目 一 zxing 谷歌的zxing技术生成二维码,是MultiFormatWriter多写格式书写器生成BitMatrix位矩阵,然后将位矩阵的信息在BufferedImage中设置二维码…

工业质检/缺陷检测领域最新顶会期刊论文收集整理 | AAAI 2025【持续更新中】

会议官方论文列表&#xff1a;https://ojs.aaai.org/index.php/AAAI/issue/view/624 其中&#xff0c;2025年是第三十九届AAAI人工智能大会&#xff0c;主要对第三十九届相关论文进行梳理&#xff0c;当前已初版28期(volume 39 no. 28) 【Attention】 虽然本文主要面向的领域…

数据结构实验8.1:图的基本操作

文章目录 一&#xff0c;实验目的二&#xff0c;实验内容三&#xff0c;实验要求四&#xff0c;算法分析五&#xff0c;示例代码8-1.cpp源码graph.h源码 六&#xff0c;操作步骤七&#xff0c;运行结果 一&#xff0c;实验目的 1&#xff0e;掌握图的邻接矩阵、邻接表的表示方…

Spring Boot3 实现定时任务 每10分钟执行一次,同时要解决分布式的问题 区分不同场景

在Spring Boot 3中实现分布式定时任务&#xff0c;确保多实例环境下任务仅执行一次&#xff0c;可以采用以下方案&#xff1a; 方案一&#xff1a;Redis分布式锁&#xff08;推荐&#xff09; import org.springframework.data.redis.core.StringRedisTemplate; import org.sp…

WPF MVVM入门系列教程(五、命令和用户输入)

&#x1f9ed; WPF MVVM入门系列教程 一、MVVM模式介绍二、依赖属性三、数据绑定四、ViewModel五、命令和用户输入六、ViewModel案例演示 WPF中的命令模型 在WPF中&#xff0c;我们可以使用事件来响应鼠标和键盘动作。 但使用事件会具备一定的局限性&#xff0c;例如&#x…

2025年01月09日德美医疗前端面试

目录 vue2 的双向绑定的原理vue3 的双向绑定原理vue 的生命周期vue 子组件为何不能修改父组件的值js delete 删除数组的某一个值会怎么样vue 和 react 的 diff 算法什么是闭包原型链this指向 vue2 的双向绑定的原理 以下是 Vue 2 双向绑定的原理&#xff1a; 1. 核心概念 …