形态学处理

news2024/11/25 4:05:57

形态学处理的相关内容

(1)基于图像形态进行处理的一般方法

(2)这些处理方法基本是对二进制图像进行处理

(3)卷积核决定着图像处理后的结果

形态学图像处理

(1)腐蚀(简单来说就是黑色图像的部分腐蚀掉白色部分,黑色部分变大)和膨胀(与腐蚀相反,白色部分变大)

(2)开运算:就是先腐蚀后膨胀这样一个组合运算

(3)闭运算:就是先膨胀后腐蚀这样一个组合运算

(4)顶帽,黑帽

图像二值化

为什么要学习二值? 刚刚在上面就提到,我们在对图像进行形态学处理的时候需要对图像处理,而这个图像最好就是二进制图像。

图像二值化相关知识 

(1)二值化就是将图像每个像素变成两种值。如0,255

(2)全局二值化 :就是对整张图片进行操作,超过一定的值就变成255,低于这个值就变成0。不让中间有灰度图像。

(3)局部二值化:就是对图像先分割成很多块,每一块都不一样。

二值化API:threshold(img,thresh,maxVal,type)

img:就是图像,是灰度图

thresh:阈值

maxVal:高于阈值变maxVal,低于阈值变0

type:THRESH_BINARY 高于阈值变最大值低于变最小值    THRESH_BINARY_INV与前一种反向高于变最小值,低于变最大值   THRESH_TRUNC    THRESH_TPZERO     THRESH_TOZERO_INV

上图中第一个图像时原图,第二个与第三个是 THRESH_BINARY,THRESH_BINARY_INV。我们可以看出当高于阈值时,BINARY变成设定最大值,BINARY_INV变成设定最小值,低于阈值时,BINARY变成设定最小值,BINARY_INV变成设定最大值。第三个是TRUNC ,它其实就不是二值化图像了,它在低于阈值时不变,高于阈值时全部变为设定的阈值,进行消峰处理。第四个和第五个是THRESH_TPZERO_INV,THRESH_TPZERO,TPZERO_INV在未达到阈值时不变,达到阈值时变为最小值,TPZERO在未达到阈值时变为最小值,达到阈值时不变。

图像二值化实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/fushipzhang.png')
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# #自己设置阈值大小 thresh
ret, dst = cv2.threshold(img1, 100, 255, cv2.THRESH_BINARY)
# # ret,dst=cv2.threshold(img1,100,255,cv2.THRESH_BINARY_INV) #黑白颜色变换
# print(ret)

cv2.imshow('img', img)
cv2.imshow('gray', img1)
cv2.imshow('dst', dst)

cv2.waitKey(0)

 

最终输出的结果如上,大家可以自己选择不同的阈值进行尝试,看看会出现什么样的区别。

腐蚀

腐蚀的相关知识

腐蚀的原理:其实腐蚀就是一个卷积核去扫描整个图像,只有当卷积核扫描到的全为1的时候,此时卷积核中心才为1,否则只要有0就为0.也就是说,当我扫描图像时,扫描全为白色时,才为白色,否则就是黑色,因此可以想象出来,黑色注定会腐蚀掉原图中旁边有黑色的白色。

这就是进过腐蚀后出现的现象,可以看出,黑色腐蚀了一部分的白色。

腐蚀的API: erode(img,kernel,iterations=1)

img:对哪张图像进行膨胀

kernel:卷积核大小

iterations:卷积的次数

腐蚀实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/erode.png')

# 腐蚀 矩阵中全为1 只有当图像中一块全为1时 才会被腐蚀为1 (一块白才为白) kernel是卷积核
# #手动设置卷积核
kernel=np.ones((9,9),np.uint8)

img1 = cv2.erode(img, kernel, iterations=1)

cv2.imshow('img', img)
cv2.imshow('img1', img1)

cv2.waitKey(0)

我们思考是否和我们原理是相同的,黑色注定会腐蚀掉旁边的白色,所以从第一张图到第二张图,蜘蛛白色的八肢被腐蚀掉,并且黑色的眼睛变大了。大家也可以改变kernel的大小,看看会出现什么情况。

卷积核的类型

卷积核类型相关知识

刚刚我们在腐蚀操作中自己设置了卷积核,但其实opencv有自带的卷积核,我们可以直接调用

获得卷积核API:getStructuringElement(type,size)

type:卷积核类型  MORPH_RACT(矩形)  MORPH_ELLIPSE(椭圆形)   MORPH_CROSS(十字形)

size:卷积核大小(3,3)(5,5)……

卷积核类型实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/erode.png')

# 从opencv中获得卷积核 cv2.getStructuringElement(type,size)
# MORPH_RECT矩形 MORPH_ELLIPSE椭圆形 MORPH_CROSS交叉十字    size值为(3,3).(5,5)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))
# kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (9, 9))
# print(kernel)   #结果是一个全1的九成九的矩阵

img1 = cv2.erode(img, kernel, iterations=1)

cv2.imshow('img', img)
cv2.imshow('img1', img1)

cv2.waitKey(0)

此时我们选取的时 MORPH_RACT(矩形) 这样的卷积核,并且我们设置的大小时(9,9),此时得出的图片与我们腐蚀部分自己设置的kernel最终结果时相同的,因为都是9x9的矩阵。大家也可以尝试不同的type看看结果有什么不同。

膨胀

膨胀的相关知识

膨胀就是把白色膨胀了,在卷积核扫过的区域只要有白色就变成白色。所以可以看出上图经过膨胀后白色变大了。

膨胀API:dilate(img,kernel,iterations=1)

img:对哪个图像进行膨胀

kernel:卷积核大小

iterations:卷积的次数

膨胀实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/erode.png')

# 膨胀 只要矩阵内有1(白)整个区域都会变成白色
# kernel=np.ones((3,3),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
dst = cv2.dilate(img, kernel, iterations=1)

cv2.imshow('img', img)
cv2.imshow('dst', dst)
# cv2.imshow('dst1',dst1)

cv2.waitKey(0)

 

原本的小瘦子变成了小胖子。白色的部分进行了膨胀,得到了我们想要的结果。 

大家思考在正常情况下,我先腐蚀,再膨胀,如果其中kernel是相同的,type是相同的,那是否会得到相同的结果?

不一定,如果进行腐蚀,图像每个部分的特征都保留下来了,那进行相反的膨胀结果是相同的,但是如果想我们上面这个图,蜘蛛的眼睛进过膨胀消失了,相反的腐蚀不会出现眼睛了,那结果就不相同了。

开运算

开运算=腐蚀+膨胀

开运算相关知识

开运算有什么用?

上图就是开运算的作用,在保持我需要的图像不变的情况下,消除旁边白色的噪点。

先腐蚀,黑色把白色的小点腐蚀掉后,此时中间的图像也会变瘦,之后进行膨胀,中间图像恢复到原状,但是由于一开始腐蚀已经去掉了白色的小点,那膨胀并不会使消失的小白点出现,所以就完成了保留主要图案,消除白色小点的任务。

开运算API: morphologyEx(img,MORPH_OPEN,kernel)

img:对哪张图片进行开运算

MORPH_OPEN:开运算

kernel:卷积核大小

开运算实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/erode.png')

# 膨胀 只要矩阵内有1(白)整个区域都会变成白色
# kernel=np.ones((3,3),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))

# #开运算 (先腐蚀后膨胀)(有很多白色的噪点,通过开运算进行消除)
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.imshow('img', img)
cv2.imshow('dst', dst)

cv2.waitKey(0)

开运算先腐蚀,把脚都给腐蚀掉了,膨胀也没恢复回来。

闭运算

闭运算=膨胀+腐蚀

闭运算相关知识

闭运算有什么用?

 把不要的黑色小点去掉。

如图中,中心这个人的图像希望保留,但是人里面的黑色小点想要去除。就可以使用闭运算。 

先膨胀,白色把黑色的小点膨胀掉后,此时中间的图像会变胖,之后进行腐蚀,中间图像恢复到原状,但是由于一开始膨胀已经去掉了黑色的小点,那腐蚀并不会使消失的小黑点出现,所以就完成了保留主要图案,消除黑色小点的任务。

闭运算API: morphologyEx(img,MORPH_CLOSE,kernel)

img:对哪张图片进行开运算

MORPH_CLOSE:闭运算

kernel:卷积核大小

闭运算实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/erode.png')

# kernel=np.ones((3,3),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))

# #闭运算(先膨胀后腐蚀)(有很多黑色的噪点,通过闭运算进行消除)
dst1 = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.imshow('img', img)
cv2.imshow('dst1', dst1)

cv2.waitKey(0)

 

开运算先膨胀,把小蜘蛛的小眼睛给膨胀消失了,后腐蚀使蜘蛛大小恢复。 

形态学梯度

梯度=原图—腐蚀

形态学梯度相关知识

腐蚀会使原来的人变小,那用原图减去变小后的图片,就得到了这个人的边沿。 

梯度API:morphologyEx(img,MORPH_GRADIENT,kernel)

形态学梯度实战代码

import cv2
import numpy as np

img = cv2.imread('../MM/erode.png')

# kernel=np.ones((3,3),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# #梯度 (原图-腐蚀后的图)
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

cv2.imshow('img', img)
cv2.imshow('dst', dst)

cv2.waitKey(0)

 

大家思考是不是应该得到上面的图像,首先进行腐蚀四肢变细了,后面使用原图减去腐蚀的图像得到结果。

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))

我把kernel大小改成7x7,结果会变成下图。

是否是这样的,大家思考?

顶帽运算与黑帽运算

顶帽运算与黑帽运算相关知识

顶帽=原图—开运算

只想要这个小的方块,不想要大的,就可以使用顶帽运算 。

顶帽运算API:morphologyEx(img,MORPH_TOPHAT,kernel)

黑帽=原图—闭运算

得到大块中的黑色的小噪点。

黑帽运算API:morphologyEx(img,MORPH_BLACKHAT,kernel)

顶帽运算与黑帽运算实战代码

顶帽:

import cv2
import numpy as np

img = cv2.imread('../MM/tophat.png')

# kernel=np.ones((3,3),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (19, 19))
# dst = cv2.dilate(img, kernel, iterations=1)

# 顶帽运算(原图-开运算)保留了白色的噪点
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

cv2.imshow('img', img)
cv2.imshow('dst', dst)

cv2.waitKey(0)

顶帽运算后留下了小的方块,但是在这种操作中需要注意kernel大小的选择,需要进行尝试。

黑帽:

import cv2
import numpy as np

img = cv2.imread('../MM/dotinj.png')

# kernel=np.ones((3,3),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))

# 黑帽运算(原图-闭运算)保留了黑色的噪点
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

cv2.imshow('img', img)
cv2.imshow('dst', dst)

cv2.waitKey(0)

 

得到黑色的小噪点。 

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

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

相关文章

如何打包鸿蒙应用并发布到应用市场

知识点: HarmonyOS 应用打包后的文件为.app 格式, android 打包后的文件为.apk,IOS 打包后的文件为.apa HarmonyOS通过数字证书(.cer文件)和Profile文件(.p7b文件)等签名信息来保证应用的完整性…

最常见的SQL报错注入函数(floor、updatexml、extractvalue)及payload总结

SQL报错注入是一种常见的SQL注入攻击方式,攻击者通过注入恶意代码,触发数据库的错误响应,并从错误信息中获取有用的信息。 下面介绍最常见的三个报错注入函数用法及payload总结: 1、floor() 使用floor报错注入,需要…

VS2020使用MFC开发一个贪吃蛇游戏

背景: 贪吃蛇游戏 按照如下步骤实现:。初始化地图 。通过键盘控制蛇运动方向,注意重新设置运动方向操作。 。制造食物。 。让蛇移动,如果吃掉食物就重新生成一个食物,如果会死亡就break。用蛇的坐标将地图中的空格替换为 #和”将…

[动态规划]完全背包问题及其优化

题目描述 有N种物品和一个容量为 V 的背包,每种物品都有无限件可用。 第 i 种物品的体积是Ci,价值是Wi。求解在不超过背包容量的情况下,能够获得的最大价值。 输入 第一行为两个整数N、V(1≤N,V≤10000),分别代表题目描述中的物…

java 怎么读取文件创建时间?

Java读取文件创建时间的实现方法 在工作时候,我们有时候需要获取到文件的最后更新时间,根据最近更新时间,来处理其他业务。那么,在Java中,怎么获取到文件最后更新时间呢?接下来凯哥(个人号:凯哥…

教你应对Github最新的2FA二次验证! 无地区限制, 你的Github账户可能被封禁!

文章目录 2FA 定义2FA验证方法1 硬件令牌2.推送通知3.SMS 验证4 基于语音的身份验证 解决方案安装身份验证器的谷歌浏览器插件打开 github 的二维码,直接扫描 2FA 定义 双因素身份验证 (2FA) 是一种身份和访管理安全方法,需要经过两种形式的身份验证才能…

大数据----MapReduce实现统计单词

目录 一、简介二、实现单词统计数据准备编程MapReduceJob 三、运行四、结果 一、简介 Hadoop MapReduce 是一个编程框架,它可以轻松地编写应用程序,以可靠的、容错的方式处理大量的数据(数千个节点)。 正如其名,MapReduce 的工作模式主要分…

每日一题——Leetcode908

方法一 数学思想&#xff1a; 其实就是看数组中最大值和最小值一个加上k一个减去k是否能刚好凑到0&#xff0c;如果不能就是两者之差 var smallestRangeI function(nums, k) {var min9999,max-1for(var i0;i<nums.length;i){min Math.min(min,nums[i])max Math.max(max…

Python数据分析 Matplotlib篇 基本方法初识 (第1讲)

Python数据分析 Matplotlib篇(第1讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…

leetcode 1576. 替换所有的问号(easy)(优质解法)

链接&#xff1a;1576. 替换所有的问号 代码&#xff1a; class Solution {public String modifyString(String s) {char[] charSs.toCharArray();int lengthcharS.length;//遍历找到 &#xff1f;for(int i0;i<length;i){if(charS[i]?){//遍历 a ~ z 选择一个合适的字符来…

Linux怎么解压zip格式文件?

Linux解压命令zip是一种常见的文件压缩格式&#xff0c;用于把文件打包成一个zip文件&#xff0c;当我们需要共享或是发送时&#xff0c;能够更快速的发送&#xff0c;储存起来能够减少储存空间。那我们在Linux上怎么使用解压命令zip来解压zip格式文件呢&#xff1f;我们一起来…

MySQL 大数量left join 太慢语句拆分的一种办法

最近做点股市分析&#xff0c;发现日线数据已经达到了千万级&#xff0c;想做个两个日期之间的收盘价比较&#xff0c;例如第一周1月3日和1月6日的涨幅&#xff0c;很简单的语句&#xff0c;如下&#xff1a; select a.scode,s. name,a.sdate sdate1,a.close close1, b.sdate …

nodejs+vue+ElementUi房屋房产销售预约看房系统bqv00

完成房产销售系统&#xff0c;对房源的信息、用户信息及各种资料进行收集和科学的管理&#xff0c;该系统的功能基本可以满足当前市面上的小型房产企业对于房产销售的基本要求&#xff0c;收集各个地区的房源信息并进行分类管理&#xff0c;用户通过注册账号登录网站查询房源信…

小狐狸ChatGPT付费创作系统 前端对话提示undefined index:temperature解决方法

很多会员使用着ChatGPT付费创作系统&#xff0c;特别是新安装系统后前端输入对话时提示错误undefined index:temperature&#xff0c;检查了反代、检查了KEY均正常&#xff0c;这问题主要是因为后台设置里新用户免费送对话次数为空&#xff0c;没设置赠送次数原因&#xff0c;导…

【BEV感知算法概述——下一代自动驾驶感知算法】

文章目录 BEV感知算法概念BEV感知算法数据集介绍BEV感知算法分类BEV感知算法的优劣小结 BEV感知算法概念 Bird’s-Eye-View&#xff0c;鸟瞰图&#xff08;俯视图&#xff09;。BEV感知算法存在许多的优势。 首先&#xff0c;BEV视图存在遮挡小的优点&#xff0c;由于视觉的透…

腾讯面试:SaaS多租户,如何设计?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业网易、美团、字节、如阿里、滴滴、极兔、有赞、希音、百度、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 多租户设计&#xff0c;如何 技术选型&#xff…

分布式事务2PC二阶段提交详解

文章目录 概述和概念执行过程和工作流程特点优劣势应用场景总结demo代码样例 概述和概念 二阶段提交&#xff08;2PC&#xff09;是一种用于确保在分布式系统中的所有节点在进行事务提交时保持一致性的算法 二阶段提交&#xff08;Two-Phase Commit&#xff0c;2PC&#xff09…

JWT、session、token区别和实现

JWT、session、token区别和实现 这里需要用到Redis和JWT。 springboot版本是3.2.1 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency><…

vitis HLS中实现canny算法的IP核

一、前言 canny边缘检测主要用于提取图像的边缘&#xff0c;是最常用且有效的边缘检测算法。在AMD赛灵思提供的库函数中&#xff0c;使用xf::cv::Canny和xf::cv::EdgeTracing两个函数实现canny边缘提取。本文举例说明如何在vitis HLS 2023.1中实现canny算法。 二、xf::cv::Cann…

GoogLeNet(V1)

目录 一、GooLeNet介绍 1、模型设计的motivation 2、Inception块 3、GoogLeNet架构 4、Inception后续变种 5、总结 二、代码实现 1、Inception块 2、GoogLeNet模型 3、训练模型 4、总结 一、GooLeNet介绍 GoogLeNet是由Google团队于2014年提出的深度卷积神经网络架构…