第九章 形态学图像处理

文章目录

  • 9形态学图像处理
    • 9.1预备知识
    • 9.2腐蚀与膨胀
      • 9.2.1腐蚀
      • 9.2.2膨胀
      • 9.2.3对偶性
    • 9.3开操作和闭操作
    • 9.4击中或击不中变换
    • 9.5一些基本形态学方法
      • 9.5.1边界提取
      • 9.5.2空洞填充
      • 9.5.3连通分量的提取
      • 9.5.4凸壳
      • 9.5.5细化
      • 9.5.6粗化
    • 9.6灰度级形态学
      • 9.6.3一些基本的形态学算法

9形态学图像处理

9.1预备知识

图像形态学也叫数学形态学,是指一系列处理图像形状特征的图像处理技术,是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论。其基本思想是利用一种特殊的结构元来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。形态学方法的基础是集合论。
常见图像形态学运算:腐蚀、膨胀、开运算、闭运算、骨架抽取、极线腐蚀、击中击不中变换、Top-hat变换、颗粒分析、流域变换、形态学梯度等。其中最基本的形态学操作是:膨胀(dilation)和腐蚀(erosion)两种操作,腐蚀和膨胀的主要作用有:消除噪声;分割出独立的图像元素,在图像中连接相邻的元素;寻找图像中明显的极大值或极小值区;求出图像的梯度等

不做特殊说明,输入图像为二值图像。图像中1是前景,0是背景。

构元(Structuring Elements,SE)可以是任意形状,SE中的的值可以是0或1。常见的结构元有矩形和十字形。结构元有一个锚点O,O一般定义为结构元的中心(也可以自由定义位置)。如下图所示是几个不同形状的结构元,紫红色区域为锚点O。
在这里插入图片描述

整个结构元我们可以使用一个 正方形的模板矩阵来表示,窗口大小wnd_size表示矩阵的宽高,模板数据元素值为0或者1,1表示结构元中对应元素要起作用。通过标记不同的元素值,我们可以使用模板矩阵来表示任意形状的结构元。

9.2腐蚀与膨胀

9.2.1腐蚀

表示为 A ⊖ B A\ominus B AB的B对A的腐蚀定义为: A ⊖ B = { z ∣ ( B ) z ⊆ A } A\ominus B=\left\{z\mid\left(B\right)_{z}\subseteq A\right\} AB={z(B)zA}
表面上,该式指出B对A的腐蚀是一个用z平移的B包含在A中的所有的点z的集合。假定集合B是一个结构元,因为B必须包含在A中这一陈述等价于B不与背景共享任何公共元素,故我们可以将腐蚀表达为如下的等价形式: A ⊖ B = { z ∣ ( B ) z ∩ A c = ∅ } A\ominus B=\left\{z\mid\left(B\right)_z\cap A^c=\varnothing\right\} AB={z(B)zAc=}

import cv2
import numpy as np
import matplotlib.pyplot as plt
import random
import math
def cv2_show(*args):
    for ttt in range(len(args)):
        img=args[ttt]
        cv2.imshow('img', img)
        cv2.waitKey(0)    
        cv2.destroyAllWindows() 

def plt_show(*args):
    plt.figure(figsize=(12, 6)) 
    for ttt in range(len(args)):
        img = args[ttt]
        if (len(img.shape) == 3):
            img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
        elif (len(img.shape) == 2):
            img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
        plt.subplot(231+ttt), plt.imshow(img)

img=cv2.imread('dige.png',0)
kernel = np.ones((3,3),np.uint8) 
num=[[]]*6
for i in range(6):
    num[i] = cv2.erode(img,kernel,iterations = i)
plt_show(num[0],num[1],num[2],num[3],num[4],num[5])

在这里插入图片描述

可看出腐蚀操作使得线条变细直至消失

9.2.2膨胀

表示为 A ⊕ B A\oplus B AB的B对A的膨胀定义为 A ⊕ B = { z ∣ ( B ^ ) z ∩ A ≠ ∅ } A\oplus B=\left\{z\mid(\hat{B})_{z}\cap A\neq\emptyset\right\} AB={z(B^)zA=}
这个公式是以B关于它的原点的映像,并且以z对映像进行平移为基础的。B对A的膨胀是所有位移z的集合,这样,B和A至少有一个元素是重叠的。根据这种解释,式子可以等价地写为 A ⊕ B = { z ∣ [ ( B ^ ) z ∩ A ] ⊆ A } A\oplus B=\left\{z\mid[(\hat{B})_z\cap A]\subseteq A\right\} AB={z[(B^)zA]A}

img=cv2.imread('dige.png',0)
kernel = np.ones((3,3),np.uint8) 
num=[[]]*6
for i in range(6):
    num[i] = cv2.dilate(img,kernel,iterations = i)
plt_show(num[0],num[1],num[2],num[3],num[4],num[5])

在这里插入图片描述

可看出线条不断变粗

9.2.3对偶性

膨胀和腐蚀彼此关于集合求补运算和反射运算是对偶的,即 ( A ⊖ B ) c = A c ⊕ B ^ (A\ominus B)^c=A^c\oplus\hat{B} (AB)c=AcB^ ( A ⊕ B ) c = A c ⊖ B ^ \left(A\oplus B\right)^{c}= A^{c}\ominus \hat{B} (AB)c=AcB^

9.3开操作和闭操作

  • 开运算:先腐蚀,后膨胀
  • 闭运算:先膨胀,后腐蚀

结构元B对集合A的开操作,表示为 A ∘ B A\circ B AB,其定义如下: A ∘ B = ( A ⊖ B ) ⊕ B A\circ B=(A\ominus B)\oplus B AB=(AB)B
结构元B对集合A的闭操作,表示为 A ∙ B A\bullet B AB,其定义如下: A ∙ B = ( A ⊕ B ) ⊖ B A \bullet B=(A\oplus B)\ominus B AB=(AB)B

kernel = np.ones((5,5),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
plt_show(img,opening,closing)

在这里插入图片描述

图一为原图,图二和图三分别为开操作和闭操作后的结果

9.4击中或击不中变换

  • 作用:在二值图像中找到匹配
  • 公式: A ∗ ◯ B = ( A ⊖ B 1 ) ∩ ( A c ⊖ B 2 ) A\textcircled{*} B=(A\ominus B_1)\cap(A^c\ominus B_2) AB=(AB1)(AcB2)

9.5一些基本形态学方法

9.5.1边界提取

原图-腐蚀: β ( A ) = A − ( A ⊖ B ) \beta\left(A\right) =A-\left(A\ominus B\right) β(A)=A(AB)

a=cv2.imread('am.png',0)
kernel = np.ones((3,3),np.uint8) 
a2=cv2.erode(a,kernel,iterations = 1)
plt_show(a,a2,a-a2)

在这里插入图片描述

如图3所示,提取了边界

9.5.2空洞填充

填充公式: X k = ( X k − 1 ⊕ B ) ∩ A c k = 1 , 2 , 3 , ⋯ X_{k}=(X_{k-1}\oplus B)\cap A^c\quad k=1,2,3,\cdots Xk=(Xk1B)Ack=1,2,3,

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

img = cv.imread("dong.png")

# 二值化
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
imgray[imgray < 100] = 0
imgray[imgray >= 100] = 255

# 原图取补得到MASK图像
mask = 255 - imgray

# 构造Marker图像
marker = np.zeros_like(imgray)
marker[0, :] = 255
marker[-1, :] = 255
marker[:, 0] = 255
marker[:, -1] = 255
marker_0 = marker.copy()

# 形态学重建
SE = cv.getStructuringElement(shape=cv.MORPH_CROSS, ksize=(3, 3))
while True:
    marker_pre = marker
    dilation = cv.dilate(marker, kernel=SE)
    marker = np.min((dilation, mask), axis=0)
    if (marker_pre == marker).all():
        break
dst = 255 - marker
filling = dst - imgray

# 显示
plt.figure(figsize=(12, 6))  # width * height
plt.subplot(2, 3, 1), plt.imshow(imgray, cmap='gray'), plt.title('src'), plt.axis("off")
plt.subplot(2, 3, 2), plt.imshow(mask, cmap='gray'), plt.title('Mask'), plt.axis("off")
plt.subplot(2, 3, 3), plt.imshow(marker_0, cmap='gray'), plt.title('Marker 0'), plt.axis("off")
plt.subplot(2, 3, 4), plt.imshow(marker, cmap='gray'), plt.title('Marker'), plt.axis("off")
plt.subplot(2, 3, 5), plt.imshow(dst, cmap='gray'), plt.title('dst'), plt.axis("off")
plt.subplot(2, 3, 6), plt.imshow(filling, cmap='gray'), plt.title('Holes'), plt.axis("off")
plt.show()

在这里插入图片描述

图5为空洞填充效果图

9.5.3连通分量的提取

从二值图像中提取连通分量是许多自动图像分析应用中的核心。令A是包含一个或多个连通分量的集合,并形成一个阵列X。(该阵列的大小与包含A的阵列的大小相同).除了在对应于A中每个连通分量中的一个点的已知的每一个位置处我们已置为1(前景值)外,该阵列的所有其他元素均为0(背景值)。如下迭代过程可完成这一目的:$ X k = ( X k − 1 ⊕ B ) ∩ A k = 1 , 2 , 3 , ⋯ X_k=(X_{k-1}\oplus B)\cap A\quad k=1,2,3,\cdots Xk=(Xk1B)Ak=1,2,3,

9.5.4凸壳

如果在集合A内连接任意两个点的直线段都在A的内部、则称集合A是凸形的。任意集合S的凸壳H是包含于S的最小凸集。集合差H-S称为S的凸缺。凸壳和凸缺对于物体描绘是很有用的。这里,我们介绍一种获得集合A的凸壳C(A)的简单形态学算法。
B i , i = 1 , 2 , 3 , 4 B^i,i= 1,2,3,4 Bi,i=1,2,3,4表示下图中的4个结构元。这个过程可通过执行下式实现: X k i = ( X k − 1 ∗ ◯ B i ) ∪ A i = 1 , 2 , 3 , 4 和 k = 1 , 2 , 3 , ⋯ X_{k}^{i}=(X_{k-1}{\textcircled{*}}B^{i})\cup A \quad i=1,2,3,4 和 k=1,2,3,\cdots Xki=(Xk1Bi)Ai=1,2,3,4k=1,2,3,
其中 X 0 i = A X_0^i=A X0i=A。当该过程收敛时(即当 X k i = X k − 1 i X_k^i=X_{k-1}^i Xki=Xk1i时),我们令 D i = X k i D^i=X^i_k Di=Xki。则A 的凸壳为 C ( A ) = ⋃ i = 1 4 D i C({A})=\bigcup_{i=1}^4D^i C(A)=i=14Di
在这里插入图片描述

9.5.5细化

定义: A ⊗ B = A − ( A ∗ ◯ B ) = A ∩ ( A ∗ ◯ B ) C A\otimes B=A-(A\textcircled{*} B)=A\cap(A\textcircled{*} B)^{C} AB=A(AB)=A(AB)C

9.5.6粗化

定义: A ∙ B = A ∪ ( A ∗ ◯ B ) A\bullet B=A\cup(A\textcircled{*} B) AB=A(AB)

9.6灰度级形态学

9.6.3一些基本的形态学算法

形态学梯度:膨胀-腐蚀

img=cv2.imread('am.png',0)
kernel = np.ones((3,3),np.uint8) 
dilate = cv2.dilate(img,kernel,iterations = 1)
erosion = cv2.erode(img,kernel,iterations = 1)
img2=dilate-erosion
plt_show(img,dilate,erosion,img2)

在这里插入图片描述

上图中,(膨胀-腐蚀)可得出梯度(最后一幅图)

礼帽与黑帽

  • 礼帽 = 原始输入-开运算结果(取’刺’)
  • 黑帽 = 闭运算-原始输入(取’整体’)
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, np.ones((7,7),np.uint8) )
blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, np.ones((15,15),np.uint8) )
plt_show(img,tophat,blackhat)

在这里插入图片描述

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

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

相关文章

kotlin从入门到精通之内置类型

基本类型 声明变量 val&#xff08;value的简写&#xff09;用来声明一个不可变的变量&#xff0c;这种变量在初始赋值之后就再也不能重新赋值&#xff0c;对应Java中的final变量。 var&#xff08;variable的简写&#xff09;用来声明一个可变的变量&#xff0c;这种变量在初始…

C51单片机期末复习第八章单片机接口技术

一 总线&#xff1a; 传送同类信息的连线 三总线&#xff1a; 地址总线AB&#xff0c;数据总线DB,控制总线CB 目录(ppt给的没啥用&#xff0c;乱还不全)&#xff1a; 8.1 单片机的系统总线 8.2 简单并行I/O口扩展 8.3 可编程并行I/O口扩展 8.4 D/A转换与DAC0832应用 8…

衣服面料相关基础

总结自 BiliBili视频&#xff1a;原来衣服的面料还能这么选&#xff0c;几个方法教你买到优质的短袖&#xff0c;再也不怕买衣服踩坑了 面子里子 既不能皱巴巴 又不能不透气 混纺 涤纶 粘纤 氨纶 涤纶 不变性 挺阔感 氨纶 弹性 粘纤 吸水透气40-50% 怕热 真丝与亚麻 …

【python】js逆向基础案例——有道翻译

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 课程亮点: 1、爬虫的基本流程 2、反爬的基本原理 3、nodejs的使用 4、抠代码基本思路 环境介绍: python 3.8 pycharm 2022专业版 >>> 免费使用教程文末名片获取 requests >>> pip install req…

软件设计原则与设计模式

设计中各各原则同时兼有或冲突&#xff0c;不存在包含所有原则的设计 一&#xff1a;单一职责原则又称单一功能原则 核心&#xff1a;解耦和增强内聚性&#xff08;高内聚&#xff0c;低耦合&#xff09; 描述&#xff1a;类被修改的几率很大&#xff0c;因此应该专注于单一的…

Android 窗口实现原理

一、基本概念 1、窗口显示架构图 多窗口的核心原理其实就是分栈和设置栈边界2、Android的窗口分类 Android应用程序窗口,这个是最常见的&#xff08;拥有自己的WindowToken)譬如&#xff1a;Activity与Dialog Android应用程序子窗口&#xff08;必须依附到其他非子窗口才能存…

【刷题笔记】牛客网:链表指定区间内反转

【刷题笔记】牛客网&#xff1a;链表指定区间内反转 一、题目描述及示例 二、思路分析 1、首先&#xff0c;我们来定义一个虚拟的头节点tempHead&#xff08;原因&#xff1a;如果从第一个位置开始反转&#xff0c;则可以不用进行特殊情况考虑&#xff09;&#xff0c;并使te…

IOS工程使用OpenCV库完整步聚

1.打开Xcode15并点击Create New Project 2.引用编译好的opencv2.framework框架 选择添加其它库 选择Add Files ... 选择OpenCV源码编译生成输入的IOS平台的opencv2.framework库 opencv库要放在工程目录下,不然会找不到 成功添加opencv库的引用,现在可在工程中使用opencv库…

基于深度学习的高精度蜜蜂检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度蜜蜂检测识别系统可用于日常生活中或野外来检测与定位蜜蜂目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的蜜蜂目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型…

【C++】auto_ptr为何被唾弃?以及其他智能指针的学习

搭配异常可以让异常的代码更简洁 文章目录 智能指针 内存泄漏的危害 1.auto_ptr(非常不建议使用) 2.unique_ptr 3.shared_ptr 4.weak_ptr总结 智能指针 C中为什么会需要智能指针呢&#xff1f;下面我们看一下样例&#xff1a; int div() {int a, b;cin >&g…

ThreadPoolExecutor源码剖析

ThreadPoolExecutor源码涉及到的内容比较多&#xff0c;需要一点点的去啃和查看… ThreadPoolExecutor的核心属性 ThreadPoolExecutor的核心属性主要就是CTL。基于CTL获取到线程池的状态以及工作线程个数。 ctl是一个int类型的整数&#xff0c;內部基于AtomicInteger&#xff0…

STM32开发——ADC(烟雾传感器)

目录 1.ADC简介 2.项目简介 3.CubeMX设置 4.函数代码 1.ADC简介 作用&#xff1a;用于读取电压值&#xff0c;然后转换为数字量传给单片机&#xff0c;单片机再通过计算&#xff0c;可以得到电压值。 ADC的性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;A…

详解:阿里邮箱_阿里企业邮箱_阿里邮箱企业版

阿里邮箱是阿里云自主研发的&#xff0c;基于飞天平台自主研发的云原生分布式邮箱系统&#xff0c;阿里邮箱提供免费版、标准版、尊享版和集团版&#xff0c;企业邮箱版本不同支持的账号数也不同&#xff0c;共享网盘容量和个人网盘容量均不同&#xff0c;阿里云百科来详细介绍…

python:并发编程(二十四)

前言 本文将和大家一起探讨python并发编程的实际项目&#xff1a;win图形界面应用&#xff08;篇六&#xff0c;共八篇&#xff09;&#xff0c;系列文章将会从零开始构建项目&#xff0c;并逐渐完善项目&#xff0c;最终将项目打造成适用于高并发场景的应用。 本文为python并…

NCI Architecture

2.1 组成部分 NCI 可分为以下逻辑组件&#xff1a;  NCI 核心 NCI 核心定义了设备主机 (DH) 和 NFC 控制器 (NFCC) 之间通信的基本功能。 这使得 NFCC 和 DH 之间能够进行控制消息&#xff08;命令、响应和通知&#xff09;和数据消息交换。  传输映射 传输映射定义 N…

【C++】哈希unordered系列容器的模拟实现

文章目录 一、哈希表的模拟实现&#xff08;开散列&#xff09;1. 开散列的概念2. 开散列的节点结构3. 开散列的插入删除与查找4. 开散列整体代码实现 二、unordered系列容器的封装实现(开散列)1. 迭代器2. unordered_set和unordered_map的封装实现3. 哈希表整体源码 一、哈希表…

如何让ChatGPT制作XMind思维导图

一、使用ChatGPT辅助生成内容 给大家一个思路&#xff0c;比如我想制作《股神巴菲特给儿女的一生忠告》相关的思维导图&#xff0c;那我们可以在ChatGPT上提问“请使用markdown格式写出股神巴菲特给儿女的一生忠告的思维导图&#xff0c;以代码格式输出”。 生成后&#xff0…

【小沐学Python】Python实现Web服务器(Flask,gevent )

文章目录 1、简介1.1 功能列表1.2 支持平台1.3 安装 2、gevent入门示例2.1 文件IO2.2 MySQL2.3 redis2.4 time2.5 requests2.6 socket2.7 并发抓取文字2.8 并发抓取图片2.9 生产者 - 消费者 3、gevent其他示例3.1 StreamServer3.2 WSGI server3.3 flask3.4 websocket3.5 udp 结…

压测工具Jmeter学习

压测工具Jmeter Jmeter介绍 Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试&#xff0c;它最初被设计用于Web应用测试&#xff0c;但后来扩展到其他测试领域。 它可以用于测试静态和动态资源&#xff0c;例如静态文件、Java 小服务程序、CGI …

三层交换机与路由互联配置(华为设备)

#三层交换机与路由器配置配置 #三层交换机与路由器配置配置 路由器配置 #进入系统视图 <Huawei>system-view #关闭系统提示信息 [Huawei]undo info-center enable #配置一个环回口 [Huawei]int LoopBack 0 #配置IP地址 与 掩码 [Huawei-LoopBack0]ip address 1.1.…