08 OpenCV腐蚀、膨胀与形态学运算

news2024/11/15 17:37:07

1 腐蚀

腐蚀操作是一种形态学操作,它用于缩小二值图像中的对象,并去除图像中的噪声和细节。其基本原理是将图像中的每个像素与内核进行比较,如果内核覆盖的区域内所有像素值都为非零值,则该像素保持不变;否则,该像素的值会被更新为 0 0 0,从而实现缩小图像中的对象。腐蚀操作的效果通常与内核的大小、形状以及迭代次数有关,通过适当选择这些参数,可以实现不同程度的腐蚀效果。

在OpenCV中,可以使用 cv2.erode() 函数来进行腐蚀操作。该函数会将内核与图像进行卷积,从而得到腐蚀后的图像。具体而言,对于图像中的每个像素 ( i , j ) (i, j) (i,j),腐蚀操作会计算内核覆盖的区域 S S S 内所有像素的最小值,然后将像素 ( i , j ) (i, j) (i,j) 的值更新为该最小值。
该函数的语法如下:

cv2.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst

其中,参数含义如下:

  • src:输入图像。
  • kernel:腐蚀操作的内核。该参数是一个由非零值构成的二进制矩阵,用于定义腐蚀操作的形状和大小。内核的大小和形状会影响腐蚀程度。
  • dst:输出图像。如果未提供,则函数会创建一个与 src 具有相同尺寸和类型的输出图像。
  • anchor:内核的锚点。该参数指示内核的中心位置,用于确定内核的变换方式。默认值为 (-1, -1),表示使用内核的中心作为锚点。
  • iterations:腐蚀操作的迭代次数。该参数指示应该对图像执行多少次腐蚀操作。默认值为 1
  • borderType:边界模式。默认值为 cv2.BORDER_CONSTANT
  • borderValue:边界值。如果边界模式为 cv2.BORDER_CONSTANT,则该参数指定边界像素的值。

在定义kernel时,通常使用numpy进行创建。
示例代码:

import cv2  
import numpy as np  
  
# 读入图像  
img = cv2.imread('test.jpg')  
  
# 定义内核  
kernel = np.ones((5,5), np.uint8)  
  
# 应用腐蚀操作  
erosion = cv2.erode(img, kernel, iterations = 1)  
  
# 显示结果  
cv2.imshow('Original', img)  
cv2.imshow('Erosion', erosion)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

image.png
可以看到,仙人球的叶子被腐蚀了。

2 膨胀

膨胀操作是一种形态学操作,可以说与腐蚀正好相反,用于放大二值图像中的对象,同时去除图像中的噪声和细节。其基本原理是将图像中的每个像素与内核进行比较,如果内核覆盖的区域内至少有一个像素值为非零值,则该像素的值就被更新为 1 1 1,从而实现放大图像中的对象。膨胀操作的效果通常与内核的大小、形状以及迭代次数有关,通过适当选择这些参数,可以实现不同程度的膨胀效果。

在OpenCV中,可以使用 cv2.dilate() 函数来进行膨胀操作。该函数会将内核与图像进行卷积,从而得到膨胀后的图像。具体而言,对于图像中的每个像素 ( i , j ) (i, j) (i,j),膨胀操作会计算内核覆盖的区域 S S S 内所有像素的最大值,然后将像素 ( i , j ) (i, j) (i,j) 的值更新为该最大值。
使用 cv2.dilate() 函数来进行膨胀操作。该函数的语法如下:

cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst

其中,参数含义如下:

  • src:输入图像。
  • kernel:膨胀操作的内核。该参数是一个由非零值构成的二进制矩阵,用于定义膨胀操作的形状和大小。内核的大小和形状会影响膨胀程度。
  • dst:输出图像。如果未提供,则函数会创建一个与 src 具有相同尺寸和类型的输出图像。
  • anchor:内核的锚点。该参数指示内核的中心位置,用于确定内核的变换方式。默认值为 (-1, -1),表示使用内核的中心作为锚点。
  • iterations:膨胀操作的迭代次数。该参数指示应该对图像执行多少次膨胀操作。默认值为 1
  • borderType:边界模式。默认值为 cv2.BORDER_CONSTANT
  • borderValue:边界值。如果边界模式为 cv2.BORDER_CONSTANT,则该参数指定边界像素的值。

仍然使用上面那个仙人球的例子:

import cv2  
import numpy as np  
  
# 读入图像  
img = cv2.imread('test.jpg')  
  
# 定义内核  
kernel = np.ones((5,5), np.uint8)  
  
# 应用腐蚀操作  
erosion = cv2.dilate(img, kernel)  
  
# 显示结果  
cv2.imshow('Original', img)  
cv2.imshow('Erosion', erosion)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

image.png
这次仙人球的刺被明显放大了,有一种眼睛变近视了的感觉。LOL

3 开运算

开运算是一种常见的形态学操作,用于去除二值图像中的噪声和细节。其基本原理是先进行腐蚀操作,然后再进行膨胀操作,这样可以去除图像中的小型噪声和细节,同时保留对象的整体形状和尺寸。开运算通常用于平滑二值图像的轮廓,并且可以帮助保留对象的整体形状。
开运算可以通过串联腐蚀+膨胀完成,也可以使用CV2的自有函数cv2.morphologyEx()函数+ MORPH_OPEN来进行开运算。该函数的语法如下:

cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]) → dst

其中:

  • src:输入图像。
  • op:形态学操作类型。该参数可以是 cv2.MORPH_OPEN,表示开运算。
  • kernel:形态学操作的内核。该参数是一个由非零值构成的二进制矩阵,用于定义膨胀和腐蚀操作的形状和大小。内核的大小和形状会影响开运算程度。
  • dst:输出图像。如果未提供,则函数会创建一个与 src 具有相同尺寸和类型的输出图像。
  • anchor:内核的锚点。该参数指示内核的中心位置,用于确定内核的变换方式。默认值为 (-1, -1),表示使用内核的中心作为锚点。
  • iterations:形态学操作的迭代次数。该参数指示应该对图像执行多少次形态学操作。默认值为 1
  • borderType:边界模式。默认值为 cv2.BORDER_CONSTANT
  • borderValue:边界值。如果边界模式为 cv2.BORDER_CONSTANT,则该参数指定边界像素的值。
    示例代码如下:
import cv2  
import numpy as np  
  
# 读入图像  
img = cv2.imread('test.jpg')  
  
# 定义内核  
kernel = np.ones((5,5), np.uint8)  
  
# 应用开运算  
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  
  
# 显示结果  
cv2.imshow('Original', img)  
cv2.imshow('Opening', opening)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

开运算后的效果为:
image.png

4 闭运算

与开运算相反,闭运算对图像先做膨胀,再做腐蚀。
闭运算的应用场景包括:

  1. 消除二值图像中的小孔和细节:闭运算可以填充图像中的小孔和消除细节,从而得到更加干净的图像,通常用于去除图像中的小型噪声和细节。
  2. 保留对象的整体形状和尺寸:闭运算可以保留对象的整体形状和尺寸,因为它通过先进行膨胀操作来扩大对象,然后再进行腐蚀操作来减小对象,从而保持对象的整体形状和尺寸不变。
  3. 图像分割:闭运算可以帮助分割图像中的不同对象,因为它可以将对象之间的间隙填充,从而使它们更容易被分开。
  4. 物体识别和测量:闭运算可以用于物体识别和测量,因为它可以保留对象的整体形状和尺寸,使得对象更容易被识别和测量。

在OpenCV中,可以使用cv2.morphologyEx()函数+ MORPH_CLOSE 函数来进行闭运算。
此处使用上一篇文章的主页图片进行闭运算的测试:

import cv2  
import numpy as np  
  
# 读入图像  
img = cv2.imread('test.jpg')  
  
# 定义内核  
kernel = np.ones((5,5), np.uint8)  
  
# 应用闭运算  
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)  
  
# 显示结果  
cv2.imshow('Original', img)  
cv2.imshow('Closing', closing)  
cv2.waitKey(0)  
cv2.destroyAllWindows()

image.png
可以看出部分文字细节被抹除了。

5 其他形态学运算

cv2.morphologyEx()中,还可以进行梯度运算,顶帽运算,黑帽运算。
梯度运算、顶帽运算和黑帽运算是形态学操作中常见的三种运算,它们分别用于计算图像的梯度、寻找图像中的明显区域以及寻找图像中的暗区域。它们都是通过将输入图像与某种内核进行卷积来实现的。

5.1 梯度运算

梯度运算是一种用于计算图像梯度的形态学操作。它可以用于检测图像中边缘的位置和方向。梯度运算的原理是通过计算图像中每个像素的局部梯度,从而确定该像素是否属于边缘。在OpenCV中,可以使用 cv2.morphologyEx()+cv2.MORPH_GRADIENT 函数来实现梯度运算。具体而言,分别对图像进行膨胀和腐蚀操作,然后计算两幅图像的差异来获得梯度图像。

5.2 顶帽运算

顶帽运算是一种用于寻找图像中明显区域的形态学操作。它可以帮助找到图像中比周围区域更亮或更暗的区域。顶帽运算的原理是通过对图像进行计算原始图像与开运算图像的差值,从而获得顶帽图像。在OpenCV中,可以使用 cv2.morphologyEx()+cv2.MORPH_TOPHAT 函数来实现梯度运算。

5.3 黑帽运算

黑帽运算是一种用于寻找图像中暗区域的形态学操作。它可以帮助找到图像中比周围区域更暗的区域。黑帽运算的原理是通过对图像进行闭运算和开运算来计算闭运算图像与原始图像的差值,从而获得黑帽图像。在OpenCV中,可以使用 cv2.morphologyEx()+cv2.MORPH_BLACKHAT 函数来实现梯度运算。

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

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

相关文章

django+vue项目搭建,前后端通信打通,

文章目录django 环境搭建1.创建django骨架项目2.创建应用3.试着启动项目,验证环境OK4.基础配置admin.pysettings.py前端项目搭建1.安装vue-cli2.创建前端项目3.创建时候选什么前端项目结构页面上呈现的内容是怎么来的?这里只说明vue部分曲线救国打通vue和…

Linux软件管理YUM

目录 yum配置文件 创建仓库 yum查询功能 yum安装与升级功能 yum删除功能 yum仓库产生的问题和解决之道 yum与dnf 网络源 YUM就是通过分析RPM的标头数据后,根据各软件的相关性制作出属性依赖时的解决方案,然后可以自动处理软件的依赖属性问题&…

1.1 什么是并发

1.1 什么是并发 并发:指两个或更多独立的活动同时发生。并发在生活中随处可见。我们可以一边走路一边说话,也可以两只手同时做不同的动作。 1.1.1 计算机系统中的并发 当我们提到计算机术语的“并发”,指的是在单个系统里同时执行多个独立…

零入门kubernetes网络实战-15->基于golang编程实现给ns网络命名空间添加额外的网卡

《零入门kubernetes网络实战》视频专栏地址 https://www.ixigua.com/7193641905282875942 本篇文章视频地址(稍后上传) 本篇文章主要是想通过golang编程来实现,为veth pair链接的网络命名空间添加网卡,配置veth pair的IP 即,使用代码创建一…

002 常见量化交易平台使用

常见的量化交易平台:米筐,BigQuant,优矿,聚宽,掘金。 本文简单介绍其中的米筐量化交易平台。米筐支持Python,Java编写交易策略进行回测。 一、平台使用 1. 注册账号 平台网址:米筐量化平台 平…

linux内存申请

一、基本概念 1、页:struct page ,如下图所示,x86架构下一般为4K为大小 2、分区:struct zone ,如下图所示,x86架构下分为三个区ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM 3、ZONE_DMA,一般由于内存…

代码随想录算法训练营第二天 | 977.有序数组的平方 、209.长度最小的子数组 、59.螺旋矩阵II、总结

打卡第二天,认真做了两道题目,顶不住了好困,明天早上练完车回来再重新看看。 今日任务 第一章数组 977.有序数组的平方209.长度最小的子数组59.螺旋矩阵II 977.有序数组的平方 给你一个按 非递减顺序 排序的整数数组 nums,返回 每…

知识图谱构建技术综述

摘要 *知识图谱为实现语义化智能搜索以及知识互联打下了基础,。, *随着知识的发展,传统的基于模板和规则构建的知识图谱已经被深度学习所替代。 知识组织得原则中:知识的充分性、有序性和标准化规则。深度学习的效果在很大程度上…

线性神经网络(线性回归)

线性回归 目录线性回归导包生成数据集观察散点图读取数据集初始化模型参数定义模型定义损失函数定义优化算法训练简易实现(pytorch)生成数据集读取数据集定义模型初始化模型参数定义损失函数定义优化算法训练导包 import random import torch from d2l import torch as d2l生成…

微服务相关概念

一、谈谈你对微服务的理解,微服务有哪些优缺点?微服务是由Martin Fowler大师提出的。微服务是一种架构风格,通过将大型的单体应用划分为比较小的服务单元,从而降低整个系统的复杂度。优点:1、服务部署更灵活&#xff1…

Python pickle模块:实现Python对象的持久化存储

Python 中有个序列化过程叫作 pickle,它能够实现任意对象与文本之间的相互转化,也可以实现任意对象与二进制之间的相互转化。也就是说,pickle 可以实现 Python 对象的存储及恢复。值得一提的是,pickle 是 python 语言的一个标准模…

2023美赛A题:受旱灾影响的植物群落

文章目录背景要求服务词汇表背景 不同的植物对压力有不同的反应。例如,草原对干旱非常敏感。干旱以不同的频率和严重程度发生。大量的观察表明,不同物种的数量对植物群落如何在连续多代干旱周期中适应起到了重要作用。在一些仅有一种植物的群落中&#…

Vue基础13之浏览器本地存储、TodoList本地存储、组件自定义事件

Vue基础13浏览器本地存储localStorage 本地存储sessionStorage 会话存储总结TodoList本地存储App.vue组件自定义事件子组件给父组件传值使用props方法App.vueSchool.vue子组件给父组件传值使用组件自定义事件——绑定第一种写法:使用v-on或App.vueStudent.vue第二种…

idea快捷编码:生成for循环、主函数、判空非空、生成单例方法、输出;自定义快捷表达式

前言 idea可根据输入的简单表达式进行识别,快速生成语句 常用的快捷编码:生成for循环、主函数、判空非空、生成单例方法、输出 自定义快捷表达式 博客地址:芒果橙的个人博客 【http://mangocheng.com】 一、idea默认的快捷表达式查看 Editor…

String对象的创建和比较

String类的概述 String类:代表字符串。 Java 程序中的所有字符串字面值(如 “abc” )都作 为此类的实例实现。 String是JDK中内置的一个类:java.lang.string 。 String表示字符串类型,属于引用数据类型,不…

饲养员喂养动物-课后程序(JAVA基础案例教程-黑马程序员编著-第四章-课后作业)

【案例4-2】饲养员喂养动物 记得 关注,收藏,评论哦,作者将持续更新。。。。 【案例目标】 案例描述 饲养员在给动物喂食时,给不同的动物喂不同的食物,而且在每次喂食时,动物都会发出欢快的叫声。例如&…

Native扩展开发的一般流程(类似开发一个插件)

文章目录大致开发流程1、编写对应的java类服务2、将jar包放到对应位置3、配置文件中进行服务配置4、在代码中调用5、如何查看服务调用成功大致开发流程 1、编写服务,打包为jar包2、将jar包放到指定的位置3、在配置文件中进行配置,调用对应的服务 1、编…

linux 之 ps命令介绍

哈喽,大家好,我是有勇气的牛排(全网同名)🐮 有问题的小伙伴欢迎在文末评论,点赞、收藏是对我最大的支持!!!。 前言 如过想实现对进程监控,就需要使用到ps命…

macOS 13.3 Beta (22E5219e)发布

系统介绍2 月 17 日消息,苹果今日向 Mac 电脑用户推送了 macOS 13.3 开发者预览版 Beta 更新(内部版本号:22E5219e),本次更新距离上次发布隔了 37 天。macOS Ventura 带来了台前调度、连续互通相机、FaceTime 通话接力…

Vue3+Lodash:2023年了,我依然在使用Lodash

目录 前言: 为什么选择lodash? 看看lodash的地位 如何使用lodash? 1.安装lodash 2.引入lodash 我们到底还需不需要lodash? 再举一些例子 前言: 前两天,在水群的时候,发现居然有人不知lodash&#…