【OpenCV实现平滑图像形态学变化】

news2024/9/23 13:27:19

文章目录

    • 概要
    • 目标
    • 腐蚀
    • 膨胀
    • 开运算
    • 结构元素(内核)
    • 小结

概要

形态学变化是一组简单的图像操作,主要用于处理二值图像,即只包含黑和白两种颜色的图像。这些操作通常需要两个输入,原始图像和一个内核(kernel),内核的形状和大小决定了操作的性质。

文章将首先介绍腐蚀和膨胀这两个基本的形态学算子。腐蚀操作通过内核在图像上滑动,将像素值置为内核覆盖区域内的最小值,用于消除图像中的小物体或者噪点。相反,膨胀操作将像素值置为内核覆盖区域内的最大值,常用于连接图像中的物体或者填充小的空洞。

随后,文章将介绍其他常见的形态学算子,如开运算和闭运算。开运算是先进行腐蚀操作,再进行膨胀操作,常用于去除噪声和分离物体。闭运算则是先进行膨胀操作,再进行腐蚀操作,常用于填充小洞和连接物体

目标

不同的形态学运算例如腐蚀、膨胀、开运算、闭运算。
不同的函数列如cv.erode()、cv.dilate()、cv.morphologyEx()等等。

腐蚀

是一种基本的形态学操作,其原理类似于自然界中的水土流失现象。在腐蚀操作中,一个内核(kernel)在图像上滑动,如果内核覆盖下的所有像素都为1(即白色,表示前景物体),那么中心像素点就会被赋值为1,否则被腐蚀掉(赋值为0)。

这种操作导致了图像中前景物体的边界被侵蚀,保持前景物体为白色的同时,减小了其厚度或尺寸。换句话说,图像中的白色区域会逐渐减小。腐蚀操作在去除小白点噪声(例如图像中的小杂点)和分离连接在一起的对象等方面非常有效。通过选择合适的内核大小,可以调整腐蚀的程度,使其更加适应不同场景下的图像处理需求。

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('img.png', 0)

# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)

# 使用腐蚀操作,iterations参数表示腐蚀操作的次数
erosion = cv.erode(img, kernel, iterations=1)

# 显示原始图像
cv.imshow('Original Image', img)

# 显示腐蚀后的图像
cv.imshow('Eroded Image', erosion)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

腐蚀结果:
在这里插入图片描述

膨胀

膨胀是一种形态学操作,与腐蚀相反。它的基本思想是通过内核的滑动,只要内核下的像素中有一个为1,中心像素就会被赋值为1(这类似于逻辑或运算)。膨胀操作会扩大白色物体(或前景物体)的区域或大小。在去除噪声时,通常会先进行腐蚀操作,然后再进行膨胀操作。这是因为腐蚀能够去除小的白色噪声,但同时也可能腐蚀掉我们需要保留的物体。膨胀操作的目的就是扩大物体,使其恢复到原始大小和形状。

在膨胀操作中,噪声已经在腐蚀阶段被去除,因此在膨胀时不会再次引入噪声,但物体的大小和体积会得到恢复。此外,膨胀操作还对有破损或间断连接的物体部分进行恢复,使其更加完整。通过膨胀操作,可以使图像中的白色区域逐渐增大,从而更好地突出物体的特征。

在这里插入图片描述

开运算

开运算只是先腐蚀后膨胀的另一个名称。正如我们上面所解释的,它对于消除噪音很有用。这里我们函数cv.morphologyEx()。

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('img.png', 0)

# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)

# 使用开运算,先腐蚀后膨胀,可以去除噪声并保持物体的整体形状
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)

# 显示原始图像
cv.imshow('Original Image', img)

# 显示开运算后的图像
cv.imshow('Opened Image', opening)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

闭运算
闭运算和开运算相反,先膨胀后腐蚀。它对于关闭前景对象内的小孔或对象上的小黑点非常有用。

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('img.png', 0)

# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)

# 使用闭运算,先膨胀后腐蚀,可以填充前景物体内部的小孔,平滑物体的边界
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

# 显示原始图像
cv.imshow('Original Image', img)

# 显示闭运算后的图像
cv.imshow('Closed Image', closing)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

形态梯度
这是图像的膨胀和腐蚀之间做了一次差
结果将看起来像只留下对象的轮廓。

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('img.png', 0)

# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)

# 使用形态梯度,通过膨胀和腐蚀的差别,突出物体的边缘
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

# 显示原始图像
cv.imshow('Original Image', img)

# 显示形态梯度后的图像
cv.imshow('Gradient Image', gradient)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

顶帽
它是输入图像和开运算图像之间的差。下面的示例是针对 9x9 内核完成的。

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('img.png', 0)

# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)

tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

# 显示原始图像
cv.imshow('Original Image', img)

# 显示形态梯度后的图像
cv.imshow('Gradient Image', tophat)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

底帽
它是闭运算图像和输入图像的差

import cv2 as cv
import numpy as np

# 读取图像
img = cv.imread('img.png', 0)

# 创建一个 5x5 的内核(矩阵)
kernel = np.ones((5, 5), np.uint8)

blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
# 显示原始图像
cv.imshow('Original Image', img)

# 显示形态梯度后的图像
cv.imshow('Gradient Image', blackhat)

# 等待用户按下任意键后关闭窗口
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

结构元素(内核)

在形态学变换中,我们经常需要定义一个内核来指导图像处理。在前面的例子中,我们手动创建了一个矩形内核,但在实际应用中,可能需要不同形状和大小的内核。为了方便地获取这些内核,OpenCV提供了一个函数cv.getStructuringElement()。

使用该函数,您只需要传递内核的形状和大小,就可以获得所需的内核。

cv.getStructuringElement(cv.MORPH_RECT, (5, 5))

如果需要一个椭圆形内核,可以使用以下代码:

cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))

类似地,如果需要一个十字形内核,可以使用

cv.getStructuringElement(cv.MORPH_CROSS, (5, 5))

小结

形态学变换是一种基于图像形状的简单而有效的处理方法,通常应用于二值图像(只包含黑白两种颜色)。在形态学变换中,我们使用内核(也称为结构化元素)来定义操作的性质和形状。

腐蚀是一种形态学变换,它侵蚀了前景物体(白色区域)的边界,通常用于去除小白点噪声或分离连接的对象。使用cv.erode()函数,我们可以将内核滑动在图像上,将内核覆盖下的像素点都为1时,中心像素点就会被赋值为1,其他时候都为0,从而缩小白色区域。

膨胀则与腐蚀相反,它会扩大白色物体的区域,常用于恢复连接对象的大小和形状。使用cv.dilate()函数,内核覆盖下的像素点只需有一个为1,中心像素点就会被赋值为1,从而扩大白色区域。

开运算是先腐蚀后膨胀的组合操作,它可以去除噪声并保持物体的整体形状。闭运算则是先膨胀后腐蚀的组合操作,它可以填充前景物体内部的小孔,平滑物体的边界。这两种操作分别使用cv.morphologyEx()函数中的cv.MORPH_OPEN和cv.MORPH_CLOSE参数实现。

为了方便地定义不同形状和大小的内核,OpenCV提供了cv.getStructuringElement()函数。通过传递内核的形状和大小参数,可以获得所需的内核。矩形、椭圆和十字形内核是常见的选择,可以根据具体任务的要求灵活选择合适的内核形状。

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

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

相关文章

计算机操作系统重点概念整理-第三章 进程同步【期末复习|考研复习】

第三章 进程同步 【期末复习|考研复习】 计算机系统系列文章传送门: 第一章 计算机系统概述 第二章 进程管理 第三章 进程同步 第四章 内存管理 第五章 文件管理 第六章 输出输出I/O管理 文章目录 第三章 进程同步 【期末复习|考研复习】前言三、进程同步3.1 临界资…

腾讯云优惠券、代金券、云服务器折扣券领取方法及使用教程

腾讯云优惠券是腾讯云为用户提供的一种优惠活动,通常包括代金券和折扣券两种类型,代金券可以在购买腾讯云相关产品时直接抵扣订单金额,而折扣券则可以在购买腾讯云相关产品时享受一定的折扣。 腾讯云作为国内领先的云计算服务提供商&#xff…

构建客户门户的痛点及低代码工具解决方案

企业如何做好数字化转型呢? 如果笼统地说起“数字化转型”,这个概念太大了,它涉及到了企业管理中的方方面面。数字化转型是一个持续不断的过程,既要在整体上进行数字规划,也需要从细节入手,将每一个步骤进…

MQTT(详解)

什么是MQTT MQTT(Message Queuing Telemetry Transport)是一种轻量级的通信协议,用于在设备之间传输消息。它通常用于物联网(IoT)和传感器网络中,可以在不同设备之间进行可靠的通信,而且资源消耗…

单元测试,集成测试,系统测试的区别是什么?

实际的测试工作当中,我们会从不同的角度对软件测试的活动进行分类,题主说的“单元测试,集成测试,系统测试”,是按照开发阶段进行测试活动的划分。这种划分完整的分类,其实是分为四种“单元测试,…

分布式消息队列:Rabbitmq(2)

目录 一:交换机 1:Direct交换机 1.1生产者端代码: 1.2:消费者端代码: 2:Topic主题交换机 2.1:生产者代码: 2.2:消费者代码: 二:核心特性 2.1:消息过期机制 2.1.1:给队列中的全部消息指定过期时间 2.1.2:给某条消息指定过期时间 2.2:死信队列 一:交换机 1:Direct交…

Gloss优化

Gloss优化,Route – Gloss – Parameters .清除不必要的线和过孔,圆滑线,焊盘中间的线,把转角变成圆弧,自动布线总会产生一些布线效果不好、多余过孔等问题。此时可以利用allegro提供的Gloss命令对设计进行优化和调整&…

Facebook广告效果数据获取

一、背景 公司每年在Facebook和Google上投放了大量的广告,我总不能让老板登录Facebook广告投放平台上去看广告效果,其实老板只关注每天花了多少钱引来了多少客户,每个客户平均花费多少钱,其它的他才不关心,有Facebook…

工作小计-GPU硬编以及依赖库 nvcuvidnvidia-encode

工作小计-GPU编码以及依赖库 已经是第三篇关于编解码的记录了。项目中用到GPU编码很久了,因为yuv太大,所以编码显得很重要。这次遇到的问题是环境的搭建问题。需要把开发机上的环境放到docker中,以保证docker中同样可以进行GPU的编码。 1 定…

SpringCloud 微服务全栈体系(五)

第七章 Feign 远程调用 先来看我们以前利用 RestTemplate 发起远程调用的代码: 存在下面的问题: 代码可读性差,编程体验不统一 参数复杂 URL 难以维护 Feign 是一个声明式的 http 客户端,官方地址:https://github.…

国家数据局正式揭牌,数据专业融合型人才迎来发展良机

文章目录 每日一句正能量摘要《数据要素安全流通》《Python数据挖掘:入门、进阶与实用案例分析》《数据保护:工作负载的可恢复性 》《Data Mesh权威指南》《分布式统一大数据虚拟文件系统 Alluxio原理、技术与实践》《云原生数据中台:架构、方…

【安装tensorflow-CPU版本】

一、安装目的二、安装过程三、总结 一、安装目的 使自己的jupyter能用tensorflow 二、安装过程 首先打开anaconda prompt 接着输入conda list 查看自己是否安装了tensorflow 在 Python 中使用 pip 工具来升级 pip 自身并指定了使用清华大学的镜像源进行安装 python -m pip …

防雷接地检测方法应用方案

防雷接地是指为了保护建筑物、设备和人员免受雷电危害而采取的将雷电电流导入地面的措施。 地凯科技防雷接地的测试方案一般包括以下几个方面: 测试目的:明确测试的对象、范围、要求和依据。 测试内容:根据不同类型的防雷接地装置&#xf…

计算机操作系统重点概念整理-第二章 进程管理【期末复习|考研复习】

第二章 进程管理 【期末复习|考研复习】 系列文章传送门: 第一章 计算机系统概述 第二章 进程管理 第三章 进程同步 第四章 内存管理 第五章 文件管理 第六章 输出输出I/O管理 文章目录 第二章 进程管理 【期末复习|考研复习】前言二、进程管理2.1进程的定义&#…

【随机过程】布朗运动

这里写目录标题 Brownian motion Brownian motion The brownian motion 1D and brownian motion 2D functions, written with the cumsum command and without for loops, are used to generate a one-dimensional and two-dimensional Brownian motion, respectively. 使用cu…

JVM虚拟机:对象在内存中的存储布局

本文重点 在前面的过程中,我们学习了对象创建过程,那么一个对象在内存中的布局是什么样的呢? 对象在内存中的存储布局 普通对象 当我们创建一个对象的时候,它由三部分组成,分别为对象头(MarkWord+class指针(指向class对象)),实例数据(对象的成员变量),填充。如果…

C++——C++入门(二)

C 前言一、引用引用概念引用特性常引用使用场景传值、传引用效率比较值和引用的作为返回值类型的性能比较 引用和指针的区别 二、内联函数概念特性知识点提升 三、auto关键字类型别名思考auto简介auto的使用细则auto不能推导的场景 四、基于范围的for循环范围for的语法范围for的…

Linux操作系统的基础IO

目录 系统文件IOopen函数0 & 1 & 2文件描述符的分配规则重定向输入重定向输出重定向追加重定向dup2 FILE 文件系统inode 软硬链接软链接硬链接 动态库和静态库动静态库的命名方式静态库制作一个库使用库 动态库制作一个库使用库 系统文件IO open函数 int open(const …

tftp服务的搭建

TFTP服务的搭建 1 先更新一下apt包 sudo apt-get update2 服务器端(虚拟机上)安装 TFTP相关软件 sudo apt-get install xinetd tftp tftpd -y3 创建TFTP共享目录 mkdir tftp_sharetftp_shaer的路径是/home/cwz/tftp_share 3.1 修改共享目录的权限 sudo chmod -R 777 tftp…

网络基础-2

IEEE制定了一个名为GARP的协议框架,该框架协议包含了两个具体协议,GMRP和GVRP。GVRP可以大大降低VLAN配置过程中的手工的工作量。 IP本身是一个协议文件的名称,该协议主要定义阐释了IP报文的格式。 类型网络号位数网络号个数主机号位数每个…