形态学处理

形态学处理的相关内容

(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)

 

得到黑色的小噪点。 

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

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

相关文章

测试C#使用AForge从摄像头获取图片

百度“C# 摄像头”关键词,从搜索结果来看,使用OpenCV、AForge、window动态链接库获取摄像头数据的居多,本文学习基于Aforge.net连接摄像头并从摄像头获取图片的基本方法。   AForge相关包(尤其是相关的控件)主要针对…

【AIPRM】-高效管理Prompt模板,让你与众多AI互动更加流畅

关于AIPRM 链接: AIPERM AIPRM:Google 推出的AI提示管理工具。它提供多样化的Prompt模板,能帮助你与各种AI进行更加高效的互动。 登录 在主页点击“免费安装”–>Add to Chrome。 安装完成后,你在新的ChatGPT界面里面,能…

【四】记一次关于架构设计从0到1的讨论

记一次关于架构设计从0到1的讨论 简介: 在一次面试中和面试官讨论起来架构设计这个话题,一聊就不知不觉一个小时了,感觉意犹未尽。现在回想起来感觉挺有意思的,古人说独学而无友则孤陋而寡闻,的确是这样的&#xff0c…

基于SSM的搬家预约系统(有报告)。Javaee项目。ssm项目。

演示视频: 基于SSM的搬家预约系统(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring Spri…

css的定位

为什么需要定位? 场景: 某个元素可以自由的在一个盒子内移动位置,并且压住其他盒子当我们滚动窗口的时候,盒子是固定屏幕某个位置的。 这二个需求,使用标准流和浮动的方式是无法实现的或者是不容易实现,所以…

date-fns v3 发布——这个由 200 个函数组成的 JavaScript 日期处理套件

date-fns v3 发布——这个由 200 个函数组成的 JavaScript 日期处理套件已经在 TypeScript 中重写,重新引入了 String 日期参数,在 Node 上支持 ESM,并且所有函数现在都可以通过命名导出导出。 经过几个月的开发,v3 终于出来了&a…

手写Vue2源码

手写Vue2 使用rollup搭建开发环境 使用rollup打包第三方库会比webpack更轻量,速度更快 首先安装依赖 npm init -ynpm install rollup rollup-plugin-babel babel/core babel/preset-env --save-dev然后添加 rollup 的配置文件 rollup.config.js import babel f…

react 路由v6

这里是区别:V5 vs V6 这里是官网:可以查看更多高级属性 一、基本使用: 1、配置文件 src/routes/index import React from "react";const Home React.lazy(() > import("../Pages/Home")); const About React.laz…

探索 HTTP 请求的世界:get 和 post 的奥秘(上)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

html之如何设置音频和视频

文章目录 前言一、音频标签:audio1.audio简介2.常用属性controlsautoplayloop代码演示: 二、视频标签:video1.video2.常用的视频元素controlsautoplayloop代码演示: 总结视频元素总结音频元素总结 前言 html中插入音频和视频的方…

超维空间S2无人机使用说明书——51、使用yolov8进行目标跟踪

引言:为了提高yolo识别的质量,提高了yolo的版本,改用yolov8进行物体识别,同时系统兼容了低版本的yolo,包括基于C的yolov3和yolov4,以及yolov7。 简介,为了提高识别速度,系统采用了G…

14章总结

一.lambda表达式 1.lambda表达式简介 lambda表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口的对象。 语法: ()->结果表达式 参数->结果表达式 (参数1,参数2,...,参数n)->…

老鹰目标检测数据集VOC格式60张

老鹰是天空中的王者,它们拥有极佳的飞行能力。它们能以惊人的速度在天空中翱翔,尤其擅长高空俯冲捕食。老鹰的视力非常敏锐,能够准确地发现地面上的猎物,并迅速下落抓取。它们的爪子强而有力,足以击倒比自己体型庞大的…

顶级旗舰ET9出道,蔚来还是那个「最不计成本」的中国车品牌

作者 |张祥威 编辑 |德新 2008年,李斌和新浪的曹国伟几人一起喝酒,发了第一条微博,「天冷带围巾,心冷发微博」,一晚上涨了2000多个粉丝,他偶尔还会针砭时事,很快积累了最早一波粉丝。 创立蔚来…

各种边缘检测算子的比较研究

边缘检测算子比较研究 文章目录 边缘检测算子比较研究一、引言1.1 边缘检测的重要性1.2 研究背景与意义1.3 研究目的和论文结构 二、文献综述2.1 边缘检测概述2.2 Roberts、Prewitt、Sobel、Laplacian 和 Canny 算子的理论基础和历史2.2.1 **Roberts算子:**2.2.2 **…

全部没有问题 (一.5)

java mooc练习 基础练习: 进阶练习: final 赋值一次 局部 必须赋值 抽象类 多态测试 package com.book;public class moocDraft1 {static int variable1;public void fatherMethod(moocDraft1 a){System.out.println(variable);}public static void…

leetcode——背包问题汇总

本章来汇总一下leetcode中做过的背包问题,包括0-1背包和完全背包。 背包问题的通常形式为:有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。求解将哪些物品装入背包里物品价值总和最大。0-1背包和…

1981-2020年全国各省银行金融机构分布数据、银行金融机构数据

1981-2020年全国各省银行金融机构分布数据/银行金融机构数据 1、时间:1981-2020年 2、指标:统计年度、地区代码、地区名称、金融机构分类代码、金融机构分类名称、营业网点机构个数、营业网点就业人数、营业网点资产总额、法人机构数目、每万人拥有的网…

嵌入式软件工程师常用的

最近我换工作了,看见不同嵌入式软件工程师用的平台都不一样,所以我整理了一下。 PlatformIO: 多平台支持: PlatformIO支持多种嵌入式平台,包括Arduino、ESP8266、ESP32、STM32等,通过一致的开发接口实现平台无关性。 内…

使用ClickHouse UDF与OpenAI模型集成

本文字数:14683;估计阅读时间:37 分钟 作者:Dale McDiarmid 审校:庄晓东(魏庄) 本文在公众号【ClickHouseInc】首发 Meetup活动 ClickHouse Shenzhen User Group第1届 Meetup 火热报名中&#x…