# OpenCV 图像预处理—形态学:膨胀、腐蚀、开运算、闭运算 原理详解

文章目录

  • 形态学概念
  • 膨胀
    • 使用膨胀操作来修复裂痕
      • 示例代码
      • 关键解析:
  • 腐蚀
    • 使用腐蚀操作消除噪点
      • 示例代码:
  • 开运算—先腐蚀后膨胀
  • 闭运算—先膨胀后腐蚀

形态学概念

首先看这两张图片

在这里插入图片描述

一张图周围有大大小小的噪音和彩点,另一张图片中字母有间隙,这种效果影响了图片的质量,该如何处理图片,提高质量?

这就是形态学操作发挥作用的地方,形态学(Morphology)是图像处理中的一种技术,主要用于分析和处理图像中的结构和形状。形态学操作基于图像的形状和结构,而不是像素的具体值。它通常应用于二值图像(黑白图像),但也可以用于灰度图像。形态学操作在许多图像处理任务中发挥着重要作用,如去噪声、分割、边缘检测等。

膨胀

膨胀操作可以理解为将图像中的前景对象扩展。其基本原理是用一个结构元素扫描图像,如果结构元素至少有一个与前景(白色)部分重叠,则图像中的中心元素被设置为前景。

与卷积类似,也有一个矩阵来扫描整张图片,比如下方这个3*3矩阵,
$$
1 & 1 & 1
1 & 1 & 1
1 & 1 & 1

$$
当这个矩阵在图片扫描的时候,如果矩阵的任何元素遇到图像的像素值“1”。则与内核中心元素重叠的像素将转换为“1”。如下图所示

在这里插入图片描述

整个扫描的过程动态如下:会将橙色部分进行扩张,这就是膨胀的过程。

在这里插入图片描述

使用膨胀操作来修复裂痕

示例代码

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =3;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行膨胀操作cv::Mat eroded_image;cv::dilate(mask_image, eroded_image, element,Point(-1,-1),1);// 显示结果图像cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);waitKey();
}

关键解析:

threshold(image,mask_image,150,255,THRESH_BINARY);  //图像进行二值化

对图像进行二值化,让图像非黑即白,当然膨胀操作也可以用于彩色图像,但是会有一个问题,中心点像素会累加,会提高原来图片的亮度,扫描核越大,会导致图片越亮,直到白色看不见为止。

   cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),cv::Point(-1, -1));

创建扫描矩阵,矩阵可以任意大小,这里使用奇数n*n的矩阵 Point 取(-1,-1)代表使用中心点像素,扫描矩阵的size越大,膨胀效果越强。

  cv::dilate(mask_image, eroded_image, element,Point(-1,-1),1);

膨胀操作API ,函数原型

CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );

一般只关心前三个参数即可,输入,输出,扫描核(扫描的矩阵),Point 取(-1,-1)代表使用中心点像素,这里迭代次数为1次,同理 迭代次数越多,膨胀效果越强

效果如图:

扫描核size为 3:有效果,但仍然有裂痕

在这里插入图片描述

扫描核 size 为 5:效果增强,边缘变粗,基本上添上空隙

在这里插入图片描述

腐蚀

与膨胀相反,删除元素,它腐蚀图像的方式就像水侵蚀河岸一样。在腐蚀操作中,它将结构元素从输入图像的左向右和从上到下滑动。如果结构元素内的所有像素都大于 0,则保留原始像素值。否则,像素设置为 0。腐蚀用于去除被视为噪声的小斑点。

同样的使用膨胀操作的扫描核 3*3 全为1 的矩阵
$$
1 & 1 & 1
1 & 1 & 1
1 & 1 & 1

$$
此内核遍历图像的每个像素。如果与内核重叠的所有像素恰好是“1”,则不会发生任何更改。但是,如果任何重叠的像素恰好为“0”,则与内核的 中心 元素重叠的像素将设置为“0”。

在这里插入图片描述

腐蚀操作可视化图:

在这里插入图片描述

随着迭代次数的增加,图像像素点慢慢被腐蚀。因此,如果您需要提取粗体且周围有很多噪点的时候,可以通过侵蚀图像来消除噪点。

使用腐蚀操作消除噪点

示例代码:

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =1;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行腐蚀操作cv::Mat eroded_image;cv::erode(mask_image, eroded_image, element,Point(-1,-1),1);// 显示结果图像cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);waitKey();
}
int main()
{string imagePath = "C:\\Users\\Marxist\\Pictures\\coco\\eroding_test.jpg";string mix_image_path = "C:\\Users\\Marxist\\Pictures\\coco\\Linux.jpg";Mat image = imread(imagePath,IMREAD_GRAYSCALE);//读取灰度图像morphology_op_demo(image);return 0;
}

关键解析:

cv::erode(mask_image, eroded_image, element,Point(-1,-1),1);

函数原型:

CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() );

与膨胀API参数一致,但效果相反

腐蚀操作—内核大小3*3 迭代1次,噪点明显消除

在这里插入图片描述

腐蚀操作—内核大小5*5 迭代1次,噪点完全消除,但是图像细节也跟着丢失了

在这里插入图片描述

面对图像丢失的情况,可以进行开闭运算了

开运算—先腐蚀后膨胀

开运算是先进行腐蚀操作,再进行膨胀操作。它主要用于去除小的噪点,并保持前景物体的整体形状。

关键函数:

  morphologyEx(mask_image, opening_image, MORPH_OPEN, element);

本质上就是调用了腐蚀API和膨胀API,OpenCV为了代码简洁,将二个API 合成了一个

示例代码

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =2;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行腐蚀操作cv::Mat eroded_image;cv::erode(mask_image, eroded_image, element,Point(-1,-1),1);Mat final;// 先执行 腐蚀 然后执行膨胀morphologyEx(mask_image, final, MORPH_OPEN, element);cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);cv::imshow("final Image", final);waitKey();
}
int main()
{string imagePath = "C:\\Users\\Marxist\\Pictures\\coco\\eroding_test.jpg";string mix_image_path = "C:\\Users\\Marxist\\Pictures\\coco\\Linux.jpg";Mat image = imread(imagePath,IMREAD_GRAYSCALE);//读取灰度图像morphology_op_demo(image);return 0;
}

开运算效果:对比腐蚀过后的图像,进行稍微膨胀 补充连接细节

在这里插入图片描述

闭运算—先膨胀后腐蚀

//形态学操作 膨胀 腐蚀 ,开操作, 闭操作
void morphology_op_demo(Mat &image){Mat mask_image;threshold(image,mask_image,150,255,THRESH_BINARY_INV);  //图像进行二值化// 创建结构元素 扫描核int kernel_size =2;cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(2 * kernel_size + 1, 2 * kernel_size + 1),cv::Point(-1, -1));// 执行膨胀操作cv::Mat eroded_image;cv::dilate(mask_image, eroded_image, element,Point(-1,-1),1);Mat final;// 先执行 腐蚀 然后执行膨胀morphologyEx(mask_image, final, MORPH_CLOSE, element);cv::imshow("Original Image", mask_image);cv::imshow("Eroded Image", eroded_image);cv::imshow("final Image", final);waitKey();
}
int main()
{string imagePath = "C:\\Users\\Marxist\\Pictures\\coco\\dilation_test.jpg";string mix_image_path = "C:\\Users\\Marxist\\Pictures\\coco\\Linux.jpg";Mat image = imread(imagePath,IMREAD_GRAYSCALE);//读取灰度图像morphology_op_demo(image);return 0;
}

闭运算与开运算相反,先膨胀后腐蚀,它主要用于填补前景物体中的小孔和连接断开的物体。

闭运算效果:对比膨胀后的图像,边缘稍微细了些

在这里插入图片描述

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

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

相关文章

php连接sql server

php连接sqlserver有三种方式 一&#xff1a;odbc连接&#xff0c;废话不多说直接上代码,封装了一个单例 <?php /*** odbcServer.php* Author: Erekys*/namespace App\Model; class odbcServer{public static $server;public static $username;public static $password;pu…

基于jeecgboot-vue3的Flowable流程仿钉钉流程设计器-发送信息服务处理

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、因为仿钉钉设计器里发送消息处理是一个服务任务&#xff0c;所以要根据这个服务任务进行处理 2、这里目前只对消息进行处理&#xff0c;就是用websocket的发送方式 输入相应的内容&…

go语言Gin框架的学习路线(十)

目录 GORM的CRUD教程 查询 普通查询 定义 User 结构体 查询所有用户 查询第一个用户 总结 条件查询 内联条件 额外查询选项 高级查询 链式操作 Scopes 多个立即执行方法 GORM的CRUD教程 CRUD 是 "Create, Read, Update, Delete"&#xff08;创建、查询…

AIoTedge边缘物联网平台,开启智能物联新架构

边缘物联网平台是一种将计算能力、数据处理和应用服务部署在网络边缘的解决方案&#xff0c;旨在提高响应速度、降低带宽需求和增强数据安全。根据搜索结果&#xff0c;边缘物联网平台应具备以下功能&#xff1a; 云边协同&#xff1a; 云边一体架构&#xff0c;通过云端管理边…

【BUG】已解决:Downgrade the protobuf package to 3.20.x or lower.

Downgrade the protobuf package to 3.20.x or lower. 目录 Downgrade the protobuf package to 3.20.x or lower. 【常见模块错误】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身…

【昇腾AI创新大赛集训营南京站学习笔记】-Ascend算子开发课程

昇腾AI创新大赛训练营 14:00-14:30 基础知识-理论课 一、CANN 、达芬奇架构和算子 1.AI Core逻辑架构 达芬奇架构包含三部分&#xff1a; 1&#xff09;计算类&#xff1a;矩阵计算单元&#xff08;两个矩阵扔进去相乘&#xff09;、向量计算单元、标量计算单元 2&#xff09;控…

基于单片机控制的变压器油压油温故障检测

摘 要 在电力系统的运行中&#xff0c;通过对其核心设备变压器的故障进行检测&#xff0c;以此能够及时、准确的发现变压器的故障&#xff0c;基于单片机控制的变压器油压油温的故障检测的方法&#xff0c;利用压力传感器、温度传感器对变压器的油压、油温进行采集并送入单片机…

vCenter 错误提示 “目标主机上的vmotion接口未配置”

vCenter 错误提示 “目标主机上的vmotion接口未配置” VMware 使用 vCenter 迁移 虚拟机报错 “目标主机上的 vMotion 接口未配置”&#xff0c;配置启用 vMotion 的步骤如下&#xff1a; &#xff08;END&#xff09;

leetcode3098. 求出所有子序列的能量和

官解 class Solution(object):# 定义常量mod int(1e9 7) # 模数&#xff0c;用于防止结果溢出inf float(inf) # 无穷大&#xff0c;用于初始化时的特殊值def sumOfPowers(self, nums, k):n len(nums) # 数组长度res 0 # 用于存储最终结果# 三维动态规划表&#xff0c;…

Nacos-2.4.0最新版本docker镜像,本人亲自制作,部署十分方便,兼容postgresql最新版本17和16,奉献给大家了

基于Postgresql数据库存储的nacos最新版本2.4.0,采用docker镜像安装方式 因业务需要,为了让nacos支持postgresql,特意花了两天时间修改了源码,然后制作了docker镜像,如果你也在找支持postgresql的nacos最新版本,恭喜你,你来的正好~ nacos-2.4.0 postgresql的数据库脚本…

Apache SeaTunnel快速入门及原理和实践(一)

一、概述 主要从以下6个方面进行&#xff1a; 对数据集成做一个简单的概括对 SeaTunnel 做简单的介绍介绍 SeaTunnel 当前的原理和架构演进对当前市面上一些比较常见的数据集成工具进行对比&#xff0c;来解读一下现在市面上已经有了那么多数据集成工具&#xff0c;为什么我们…

Django Web框架——01

目录 文章目录 目录 Django框架的介绍起源&现状Django的安装 创建Django项目创建项目的指令Django项目的目录结构settings.py 文件介绍 URL 介绍URL定义Django如何处理一个URL对应的请求视图函数(view) Django 路由配置path() 函数path转换器 re_path()函数 HTTP协议的请求…

CoAP——Libcoap安装和使用(Ubuntu22.04)

1、简介 CoAP&#xff08;Constrained Application Protocol&#xff09;是一种专为受限设备和网络设计的应用层协议。它类似于HTTP&#xff0c;但具有更轻量级的特性&#xff0c;适合用于物联网&#xff08;IoT&#xff09;环境中的低功耗和低带宽设备。Libcoap是一个轻量级的…

云计算实训12——配置web服务器、配置客户端服务器、配置DNS服务、实现DNS域名解析

一、配置web服务器 准备操作 首先在正式配置之前需要做以下操作 关闭防火墙 systemctl stop firewalld 永久关闭防火墙 systemctl disable firewalld 关闭selinux setenforce 0 永久关闭selinux vim /etc/selinux/config selinuxpermissive 还需要保证能够正常ping通www.bai…

【SpingCloud】客户端与服务端负载均衡机制,微服务负载均衡NacosLoadBalancer, 拓展:OSI七层网络模型

客户端与服务端负载均衡机制 可能有第一次听说集群和负载均衡&#xff0c;所以呢&#xff0c;我们先来做一个介绍&#xff0c;然后再聊服务端与客户端的负载均衡区别。 集群与负载均衡 负载均衡是基于集群的&#xff0c;如果没有集群&#xff0c;则没有负载均衡这一个说法。 …

有哪些好用的 AI 学术研究工具和科研工具?

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频百万播放量https://aitools.jurilu.com/ AI 应用其实分两个层面&#xff0c;第一是模型&#xff0c;第二是应用。现在很多模型厂家都是既做 toC 的对话应用&#xff0c;也做 t…

GD 32 流水灯

前言&#xff1a; 通过后面的学习掌握了一些逻辑架构的知识&#xff0c;通过复习的方式将学到的裸机任务架构的知识运用起来&#xff0c;同时巩固前面学到的知识&#xff0c;GPIO的配置等。 开发板上LED引脚使用示意图 注&#xff1a;此次LED灯的点亮凡是是高电平点亮&#xff…

好用的电脑屏幕监控软件推荐,什么软件能够监控电脑?

在当今信息化时代&#xff0c;电脑屏幕监控软件成为了企业管理、家长监管以及教育培训等领域的必备工具。通过实时监控电脑屏幕&#xff0c;这类软件可以有效提高工作效率&#xff0c;防止信息泄露&#xff0c;保障网络安全。本文将详细盘点几款主流的电脑屏幕监控软件&#xf…

Linux shell编程学习笔记66:ping命令 超详细的选项说明

0 前言 网络信息是电脑网络信息安全检查中的一块重要内容&#xff0c;Linux和基于Linux的操作系统&#xff0c;提供了很多的网络命令&#xff0c;今天我们研究最常用的ping命令。 1 ping命令 的功能、格式和选项说明 1.1 ping命令 的功能 简单来说&#xff0c; ping 命令 会…

全网最适合入门的面向对象编程教程:23 类和对象的 Python 实现-抛出异常

全网最适合入门的面向对象编程教程&#xff1a;23 类和对象的 Python 实现-抛出异常 摘要&#xff1a; 本文主要介绍了在使用Python面向对象编程时&#xff0c;抛出异常的应用场景、raise语句的使用方法和raise语句语法格式&#xff0c;并举出相应示例辅助讲解。 原文链接&am…