opencv之形态学

文章目录

  • 1. 什么是形态学
  • 2. 形态学操作
    • 2.1 腐蚀
    • 2.2 膨胀
    • 2.3 通用形态学函数
    • 2.4 开运算
    • 2.5 闭运算
    • 2.6 形态学梯度运算
    • 2.7 礼帽运算
    • 2.8 黑帽运算

1. 什么是形态学

在图像处理领域,形态学是一种基于形状的图像分析技术,用于提取和处理图像的形态特征。这包括膨胀、腐蚀、开运算、闭运算等操作,广泛应用于边缘检测、图像分割和噪声去除等方面。

形态学操作的核心概念是结构元(Structuring Element),这是一个定义形态学操作如何应用于图像的形状或模板。结构元可以是任意形状的,如方形、圆形、十字形等,应用于图像时,结构元素在图像上滑动,决定了哪些像素会被膨胀、腐蚀或其他形态学操作影响。

通过组合这些基本操作,可以实现复杂的图像处理任务,如物体边界提取、骨架化、形状分析等。形态学在许多图像处理应用中具有重要作用,尤其是在需要基于形状特征进行分析的场景中。

本文的内容主要来自《OpenCV轻松入门:面向Python》这本书,他讲的比较清晰。

2. 形态学操作

2.1 腐蚀

腐蚀是最基本的形态学操作之一,它能够将图像的边界点消除,使图像沿着边界向内收缩,也可以将小于指定结构体元素的部分去除。腐蚀用来“收缩”或者“细化”二值图像中的前景,借此实现去除噪声、元素分割等功能。例如,在图1中,左图是原始图像,右图是对其腐蚀的处理结果。

图1

在腐蚀过程中,通常使用一个结构元来逐个像素地扫描要被腐蚀的图像,并根据结构元和被腐蚀图像的关系来确定腐蚀结果。

例如,在图2中,整幅图像的背景色是黑色的,前景对象是一个白色的圆形。图像左上角的深色小方块是遍历图像所使用的结构元。在腐蚀过程中,要将该结构元逐个像素地遍历整幅图像,并根据结构元与被腐蚀图像的关系,来确定腐蚀结果图像中对应结构元中心点位置的像素点的值。

图2

需要注意的是,腐蚀操作等形态学操作是逐个像素地来决定值的,每次判定的点都是与结构元中心点所对应的点。

图3中的两幅图像表示结构元与前景色的两种不同关系。根据这两种不同的关系来决定,腐蚀结果图像中的结构元中心点所对应位置像素点的像素值。

图3

● 如果结构元完全处于前景图像中(图3的左图),就将结构元中心点所对应的腐蚀结果图像中的像素点处理为前景色(白色,像素点的像素值为1)。

● 如果结构元未完全处于前景图像中(可能部分在,也可能完全不在,图3的右图),就将结构元中心点对应的腐蚀结果图像中的像素点处理为背景色(黑色,像素点的像素值为0)。

针对图3中的图像,腐蚀的结果就是前景色的白色圆直径变小。上述结构元也被称为核。

如果使用结构元kernel图(b)对图像img图(a)进行腐蚀,则可以得到腐蚀结果图像rst图(d)

图4

在OpenCV中,使用函数cv2.erode()实现腐蚀操作,其语法格式为:

式中:

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

● dst是腐蚀后所输出的目标图像,该图像和原始图像具有同样的类型和大小。

● src是需要进行腐蚀的原始图像,图像的通道数可以是任意的。但是要求图像的深度必须是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

● kernel代表腐蚀操作时所采用的结构类型。它可以自定义生成,也可以通过函数cv2.getStructuringElement()生成。

● anchor代表element结构中锚点的位置。该值默认为(-1, -1),在核的中心位置。

● iterations是腐蚀操作迭代的次数,该值默认为1,即只进行一次腐蚀操作。

● borderType代表边界样式,一般采用其默BORDER_CONSTANT。

● borderValue是边界值,一般采用默认值。在C++中提供了函数morphologyDefault BorderValue()来返回腐蚀和膨胀的“魔力(magic)”边界值,Python不支持该函数。

代码

import cv2
import numpy as np
img=np.zeros((5,5), np.uint8)
img[1:4,1:4]=1
kernel = np.ones((3,1), np.uint8)
erosion = cv2.erode(img, kernel)
print("img=\n", img)
print("kernel=\n", kernel)
print("erosion=\n", erosion)
import cv2
import numpy as np
o=cv2.imread("erode.bmp", cv2.IMREAD_UNCHANGED)
kernel = np.ones((5,5), np.uint8)
erosion = cv2.erode(o, kernel)
cv2.imshow("orriginal", o)
cv2.imshow("erosion", erosion)
cv2.waitKey()
cv2.destroyAllWindows()

2.2 膨胀

膨胀操作是形态学中另外一种基本的操作。膨胀操作和腐蚀操作的作用是相反的,膨胀操作能对图像的边界进行扩张。膨胀操作将与当前对象(前景)接触到的背景点合并到当前对象内,从而实现将图像的边界点向外扩张。如果图像内两个对象的距离较近,那么在膨胀的过程中,两个对象可能会连通在一起。膨胀操作对填补图像分割后图像内所存在的空白相当有帮助。二值图像的膨胀示例如图5所示。

图5

同腐蚀过程一样,在膨胀过程中,也是使用一个结构元来逐个像素地扫描要被膨胀的图像,并根据结构元和待膨胀图像的关系来确定膨胀结果。例如,在图6中,整幅图像的背景色是黑色的,前景对象是一个白色的圆形。图像左上角的深色小块表示遍历图像所使用的结构元。

在膨胀过程中,要将该结构元逐个像素地遍历整幅图像,并根据结构元与待膨胀图像的关系,来确定膨胀结果图像中与结构元中心点对应位置像素点的值。

图6

图7中的两幅图像代表结构元与前景色的两种不同关系。根据这两种不同关系来决定膨胀结果图像中,与结构元中心像素重合的点的像素值。

图7

● 图( a )表示待膨胀的img。

● 图( b )是核kernel。

● 图( c )中的阴影部分是kernel在遍历img时,kernel中心像素点位于img[1,1]、img[3,3]时与前景色存在重合像素点的两种可能情况,实际上共有9个这样的与前景对象重合的可能位置。核kernel的中心分别位于img[1,1]、img[1,2]、img[1,3]、img[2,1]、img[2,2]、img[2,3]、img[3,1]、img[3,2]或img[3,3]时,核内像素点都存在与前景图像重合的像素点。

● 图( d )是膨胀结果图像rst。在kernel内,当任意一个像素点与前景对象重合时,其中心点所对应的膨胀结果图像内的像素点值的为1;当kernel与前景对象完全无重合时,其中心点对应的膨胀结果图像内像素点的值为0。

图8

在OpenCV内,采用函数cv2.dilate()实现对图像的膨胀操作,该函数的语法结构为:

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

式中:

● dst代表膨胀后所输出的目标图像,该图像和原始图像具有同样的类型和大小。

● src代表需要进行膨胀操作的原始图像。图像的通道数可以是任意的,但是要求图像的深度必须是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

● element代表膨胀操作所采用的结构类型。它可以自定义生成,也可以通过函数cv2.getStructuringElement()生成。

参数kernel、anchor、iterations、borderType、borderValue与函数cv2.erode()内相应参数的含义一致。

代码

import cv2
import numpy as np
img=np.zeros((5,5), np.uint8)
img[2:3,1:4]=1
kernel = np.ones((3,1), np.uint8)
dilation = cv2.dilate(img, kernel)
print("img=\n", img)
print("kernel=\n", kernel)
print("dilation\n", dilation)

2.3 通用形态学函数

腐蚀操作和膨胀操作是形态学运算的基础,将腐蚀和膨胀操作进行组合,就可以实现开运算、闭运算(关运算)、形态学梯度(Morphological Gradient)运算、礼帽运算(顶帽运算)、黑帽运算、击中击不中等多种不同形式的运算。

OpenCV提供了函数cv2.morphologyEx()来实现上述形态学运算,其语法结构如下:

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

式中:

● dst代表经过形态学处理后所输出的目标图像,该图像和原始图像具有同样的类型和大小。

● src代表需要进行形态学操作的原始图像。图像的通道数可以是任意的,但是要求图像的深度必须是CV_8U、CV_16U、CV_16S、CV_32F、CV_64F中的一种。

● op代表操作类型,如图9所示。各种形态学运算的操作规则均是将腐蚀和膨胀操作进行组合而得到的。

图9

● 参数kernel、anchor、iterations、borderType、borderValue与函数cv2.erode()内相应参数的含义一致。

2.4 开运算

开运算进行的操作是先将图像腐蚀,再对腐蚀的结果进行膨胀。开运算可以用于去噪、计数等。

例如,在图9中,通过先腐蚀后膨胀的开运算操作实现了去噪,其中:

图10

● 左图是原始图像。

● 中间的图是对原始图像进行腐蚀的结果。

● 右图是对腐蚀后的图像进行膨胀的结果,即对原始图像进行开运算的处理结果。

从图10中可以看到,原始图像在经过腐蚀、膨胀后实现了去噪的目的。除此以外,开运算还可以用于计数。例如,在对图11中的区域进行计数前,可以利用开运算将连接在一起的不同区域划分开,其中:

图11

● 左图是原始图像。

● 中间的图是对原始图像进行腐蚀的结果。

● 右图是对腐蚀后的图像进行膨胀的结果,即对原始图像进行开运算的处理结果。

通过将函数cv2.morphologyEx()中操作类型参数op设置为“cv2.MORPH_OPEN”,可以实现开运算。其语法结构如下:

opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

2.5 闭运算

闭运算是先膨胀、后腐蚀的运算,它有助于关闭前景物体内部的小孔,或去除物体上的小黑点,还可以将不同的前景图像进行连接。例如,在图12中,通过先膨胀后腐蚀的闭运算去除了原始图像内部的小孔(内部闭合的闭运算),其中:

图12

● 左图是原始图像。

● 中间的图是对原始图像进行膨胀的结果。

● 右图是对膨胀后的图像进行腐蚀的结果,即对原始图像进行闭运算的结果。

从图12可以看到,原始图像在经过膨胀、腐蚀后,实现了闭合内部小孔的目的。除此以外,闭运算还可以实现前景图像的连接。例如,在图13中,利用闭运算将原本独立的两部分前景图像连接在一起,其中:

图13

通过将函数cv2.morphologyEx()中操作类型参数op设置为“cv2.MORPH_CLOSE”,可以实现闭运算。其语法结构如下:

closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

代码

import cv2
import numpy as np
img1=cv2.imread("closing.bmp")
img2=cv2.imread("closing2.bmp")
k=np.ones((10,10), np.uint8)
r1=cv2.morphologyEx(img1, cv2.MORPH_CLOSE, k, iterations=3)
r2=cv2.morphologyEx(img2, cv2.MORPH_CLOSE, k, iterations=3)
cv2.imshow("img1", img1)
cv2.imshow("result1", r1)
cv2.imshow("img2", img2)
cv2.imshow("result2", r2)
cv2.waitKey()
cv2.destroyAllWindows()

2.6 形态学梯度运算

形态学梯度运算是用图像的膨胀图像减腐蚀图像的操作,该操作可以获取原始图像中前景图像的边缘。

图13

2.7 礼帽运算

礼帽运算是用原始图像减去其开运算图像的操作。礼帽运算能够获取图像的噪声信息,或者得到比原始图像的边缘更亮的边缘信息。

例如,图14是一个礼帽运算示例,其中:

图14

● 左图是原始图像。

● 中间的图是开运算图像。

● 右图是原始图像减开运算图像所得到的礼帽图像。

从图15中可以看到,礼帽运算使用原始图像减开运算图像得到礼帽图像,礼帽图像是原始图像中的噪声信息。

例如,在图15中,左图是原始图像,中间的图是开运算图像,右图是原始图像减开运算图像得到的礼帽图像,礼帽图像显示的是比原始图像的边缘更亮的边缘信息。

图15
import cv2
import numpy as np
o1=cv2.imread("tophat.bmp", cv2.IMREAD_UNCHANGED)
o2=cv2.imread("lena.bmp", cv2.IMREAD_UNCHANGED)
k=np.ones((5,5), np.uint8)
r1=cv2.morphologyEx(o1, cv2.MORPH_TOPHAT, k)
r2=cv2.morphologyEx(o2, cv2.MORPH_TOPHAT, k)
cv2.imshow("original1", o1)
cv2.imshow("original2", o2)
cv2.imshow("result1", r1)
cv2.imshow("result2", r2)
cv2.waitKey()
cv2.destroyAllWindows()

2.8 黑帽运算

黑帽运算是用闭运算图像减去原始图像的操作。黑帽运算能够获取图像内部的小孔,或前景色中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。

图16

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

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

相关文章

前端与后端的身份认证

这里写目录标题 前端与后端的身份认证Web开发模式服务端渲染的Web开发模式前后端分离的Web开发模式根据场景选择开发模式 身份认证为什么需要身份认证不同开发模式下的身份认证 Session认证机制HTTP协议下的无状态性如何突破HTTP无状态的限制CookieCookie的几大特性&#xff1a…

Cadence高速板设计技巧(全志H3)[四]

HDMI常用的ESD器件: 可以看到一个器件可以做两路差分线的TVS防护: 按W键移动会把导线直接移走,这样显然是不行的: cadence中导线调节用的是快捷键e: 因此,虽然在某些场合下 eMMC 被称为 ROM,但…

Unity(2022.3.41LTS) - 地形

目录 一、地形的创建 二.页面详解 1.创建相邻的 Terrain 瓦片。 2.雕刻和绘制地形。 3.添加树。 4.添加细节,如草地、花朵和岩石。 5.更改所选 Terrain 的常规设置 三、地形编辑工具 四、地形的属性设置 五、地形的优化 六、地形的应用场景 一、地形的创…

C++八股文之语言基础篇

🤖个人主页:晚风相伴-CSDN博客 思维导图链接:C语言基础 持续更新中…… 💖如果觉得内容对你有帮助的话,还请给博主一键三连(点赞💜、收藏🧡、关注💚)吧 &…

vscode c++和cuda开发环境配置

文章目录 1. vscode 插件安装2. 开发环境配置2.1 bear 安装2.2 代码的编译2.2.1 编写Makefile文件2.2.2 bear make和make命令2.3 debug环境配置2.1 函数跳转设置2.1.1 ` c_cpp_properties.json` 设置2.1.2 settings.json设置2.2 调试环境配置2.2.1 tasks.json2.2.2 launch.json…

shell编程之条件语句(if)

目录 一、条件测试 1.1文件测试和整数测试 1.1.1 test命令 1.1.2 文件测试 1.2.3 整数值比较 1.2 字符串测试与逻辑测试 1.2.1 字符串比较 1.2.2 逻辑测试 二、if语句 2.1 if单分支语句 2.2 if双分支语句 2.3 if多分支语句 三、case分支语句 一、条件测试 1.1文件…

微信小程序背景图无法显示

文章目录 不知道有没有人跟我一样,刚接触微信小程序,在写代码的时候,背景图莫名奇妙不显示。 网上有很多解决方法,比如转 base64 ,网络图片地址等等,但我觉得都太麻烦了,这里直接给出我的解决方…

新生在线分班查询,用这个小程序制作仅需一分钟!

今天许多学校已陆续开学,老师们又开始忙碌起来。他们需要将新生的分班信息逐一通知给每位家长,这不仅是一项繁琐的工作,而且效率也不高。传统的方法是通过电话、短信或邮件一一通知,这不仅耗时耗力,还容易出现信息传递…

《大道平渊》· 拾玖 —— 做产品的四大境界

《大道平渊》 【顶级】虚空造物, 无中生有。 【上等】带脑子抄, 模仿, 改进, 超越。 【中等】无脑抄, 一模一样, 疯狂内卷。 【下等】抄都能抄错, 蠢货。 // 题外话:呵呵,很多人照着抄都能抄错,给了模板不会用,项目拆解出来嚼…

React中实现antd自定义图标,鼠标悬浮变色

借助 antd 的 tooltip 组件来实现 hover 时变色的效果 1.新建组件 自定义图标一般在iconfont上面获取,复制下来的svg代码,切记要删除 fill 属性后添加到组件中 import { Tooltip } from "antd"; import React from "react";const …

springboot篇

文章目录 1.题目问答2.配置详情2.1配置文件2.2多环境配置2.3自定义参数2.4命令行参数2.5加载顺序 3.Starter POMs4.监控与管理—actuator4.1. 应用配置类4.1.1./autoconfg4.1.2. /beans4.1.3. /configprops4.1.4 /env4.1.5./mappings4.1.6./info 4.2. 度量指标类4.2.1. /metric…

oceanbase 常用视图查询记录

测试环境:1-1-1 OceanBase 企业版3.2.4.4 查看租户的 Context 和 Modudle 内存 SELECT tenant_id, svr_ip, ctx_id, ctx_name, mod_name, count, round(HOLD / 1024 / 1024, 2) hold_mb, round(used / 1024 / 1024, 2) used_mb FROM oceanbase.__all_virtual_memory…

AI问答:.NET核心组成概要、程序运行步骤和查询SDK版本的方法

.NET三大组成 ①Runtime (运行时): CLR:公共语言运行时,执行程序、内存管理、垃圾回收(GC)、安全性检查、异常处理,是跨平台的关键要素。 JIT:实时编译器,将中间语言…

Java性能优化传奇之旅--Java万亿级性能优化之Java 性能优化传奇:热门技术点亮高效之路

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的博客,正是这样一个温暖美好的所在。在这里,你们不仅能够收获既富有趣味又极为实…

持续集成与持续部署(CI/CD)的深入探讨

在现代软件开发中,持续集成(CI)和持续部署(CD)已成为不可或缺的实践。这些方法旨在加快软件交付的速度,同时提高软件的质量和稳定性。通过CI/CD,开发团队可以频繁地将代码更改集成到主分支&…

Windows 下载安装RabbitMQ

环境描述 windows10 Erlang 26.2.x 版本 RabbitMQ 3.13.7 因为RabbitMQ是Erlang语言开发的,所以必须安装 Erlang RabbitMQ官网链接: https://www.rabbitmq.com/docs/which-erlang 1.下载并安装Erlang 26.2.5 1.1下载Erlang 26.2.5 https://erlang.org/dow…

谁便宜就选谁---基于成本的优化

什么是成本 我们之前老说MySQL执行一个查询可以有不同的执行方案,它会选择其中成本最低,或者说代价最低的那种方案去真正的执行查询。不过我们之前对成本的描述是非常模糊的,其实在MySQL中一条查询语句的执行成本是由下面这两个方面组成的&a…

数据结构:(LeetCode101)对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。 示例 1: 输入:root [1,2,2,3,4,4,3] 输出:true示例 2: 输入:root [1,2,2,null,3,null,3] 输出:false提示: 树中节点数目在范围…

基于分布式计算的电商系统设计与实现【系统设计、模型预测、大屏设计、海量数据、Hadoop集群】

文章目录 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主项目展示项目介绍 目录摘要Abstract1 引言1.1 研究背景1.2 国内外研究现状1.3 研究目的1.4 研究意义 2 关键技术理论介绍2.1 Hadoop相关组件介绍2.2 分布式集群介绍2.3 Pyecharts介绍2.4 Fl…

真北老王 8 月小结:是战士,是爱人

2024年进度条:■■■■■■■■□□□□ 跑步: 八月暑假带娃,只跑了 83 公里。首次一个人的半马 2 小时 45 分。五公里突破 31 分钟。实践跑步、徒手健身、爬楼梯、跳绳混合运动。报了顺德半马,等抽签。 读书: glenwan…