形态学操作

news2024/11/15 17:27:02

目录

1、腐蚀

1.1 腐蚀目的

1.2 原理与代码实现

2、膨胀

3、应用

3.1 开闭运算、形态学梯度

3.1.1 开运算

 3.1.2 闭运算

​编辑

 3.1.3 形态学梯度

​编辑

 3.1.4 顶帽与黑帽运算

3.2 相关函数


形态学操作常用于对二值化图像的操作

1、腐蚀

1.1 腐蚀目的

去除图像中微小物体,分离较近的两个物体

1.2 原理与代码实现

 

//绘制包含区域函数
void drawState(Mat &img, int number, Mat centroids, Mat stats, String str)
{
	RNG rng(10086);
	vector<Vec3b> colors;
	for (int i = 0; i < number; i++)
	{
		//使用均匀分布的随机数确定颜色
		Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		colors.push_back(vec3);
	}

	for (int i = 1; i < number; i++)
	{
		//中心位置
		int center_x = centroids.at<double>(i, 0);
		int center_y = centroids.at<double>(i, 1);

		//矩形边框
		int x = stats.at<int>(i, CC_STAT_LEFT);
		int y = stats.at<int>(i, CC_STAT_TOP);
		int w = stats.at<int>(i, CC_STAT_WIDTH);
		int h = stats.at<int>(i, CC_STAT_HEIGHT);

		//中心位置绘制
		circle(img, Point(center_x, center_y), 2, Scalar(0, 255, 0), 2, 8, 0);

		//外接矩形
		Rect rect(x, y, w, h);
		rectangle(img, rect, colors[i],1,8, 0);
		putText(img,format("%d",i),Point(center_x,center_y),FONT_HERSHEY_SIMPLEX, 0.5,Scalar(0, 0,255),1);
	}
	imshow(str,img);
}
//形态学操作-腐蚀
int test1()
{
	//生成用于腐蚀的原图像
	Mat src = (Mat_<uchar>(6,6) << 0,0,0,0,255,0,
	    0, 255, 255,255,255, 255,
		0, 255,255, 255,255, 0, 
		0,255,255, 255, 255, 0, 
		0,255, 255,255,255,0, 
		0, 0, 0, 0,0, 0);

	Mat struct1, struct2;

	struct1 = getStructuringElement(0,Size(3,3));//矩形结构元素
	struct2 = getStructuringElement(1,Size(3,3));//十字结构元素

	Mat erodeSrc;//存放腐蚀后的图像

	erode(src, erodeSrc,struct2);
	
	namedWindow("src", WINDOW_GUI_NORMAL);
	namedWindow("erodeSrc",WINDOW_GUI_NORMAL);
	
	imshow("src", src) ;
	imshow("erodeSrc", erodeSrc); 
	cout << "文字腐蚀验证" << endl;
	waitKey(0);

	Mat LearnCV_black = imread("F:/testMap/rice.png", IMREAD_ANYCOLOR);

	Mat erode_black1,erode_black2;
	
	//黑背景图像腐蚀
	erode(LearnCV_black,erode_black1,struct1); 
	erode(LearnCV_black, erode_black2,struct2); 
	
	imshow("LearnCV_black", LearnCV_black);
	imshow("erode_blackl", erode_black1); 
	imshow("erode_black2", erode_black2);
	cout << "验证腐蚀对小连通域的去除"<< endl;
	waitKey(0);
		
	Mat img = imread("F:/testMap/rice.png");
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确"<< endl;
		return -1;
	}
	Mat img2;
	copyTo(img,img2,img);//克隆一个单独的图像,用于后期图像绘制
	Mat rice,riceBW;

	//将图像转成二值图像,用于统计连通域
	cvtColor(img,rice,COLOR_BGR2GRAY);
	threshold(rice,riceBW,50,255,THRESH_BINARY);

	Mat out,stats, centroids;
	
	//统计图像中连通域的个数
	int number = connectedComponentsWithStats(riceBW,out,stats,centroids, 8,CV_16U);
	drawState(img,number,centroids,stats,"未腐蚀时统计连通域");//绘制图像

	erode(riceBW, riceBW, struct1);//对图像进行腐蚀
	number = connectedComponentsWithStats(riceBW, out,stats, centroids,8,CV_16U); 
	drawState(img2,number,centroids,stats,"腐蚀后统计连通域");//绘制图像


	waitKey(0);
	return 0;
}

2、膨胀

 同上

 

 

//形态学操作-膨胀
int test2()
{

	//生成用于膨胀的原图像
		Mat src = (Mat_<uchar>(6, 6) << 0,0,0,0,255,0,
		0,255,255,255,255,255,
		0,255,255,255,255,0, 
		0,255,255,255,255, 0, 
		0,255,255,255,255,0, 
		0, 0,0,0,0, 0);

	Mat struct1, struct2;

	struct1 = getStructuringElement(0,Size(3,3));//矩形结构元素
	struct2 = getStructuringElement(1,Size(3,3));//十字结构元素
	
	Mat erodeSrc;//存放膨胀后的图像
	dilate(src, erodeSrc, struct2);//膨胀

	namedWindow("src",WINDOW_GUI_NORMAL);
	namedWindow("dilateSrc",WINDOW_GUI_NORMAL); 
	imshow("src",src) ;
	imshow("dilateSrc", erodeSrc);

	cout << "文字膨胀" << endl; 
	waitKey(0);

	Mat LearnCV_black = imread("F:/testMap/learnCV_black.png", IMREAD_ANYCOLOR);
	Mat dilate_black1, dilate_black2;

	//黑背景图像膨胀
	dilate(LearnCV_black, dilate_black1, struct1); 
	dilate(LearnCV_black,dilate_black2, struct2); 
	imshow("LearnCV_black", LearnCV_black);
	imshow("dilate_black1", dilate_black1); 
	imshow("dilate_black2", dilate_black2); 


	waitKey(0);
	return 0;
}

3、应用

3.1 开闭运算、形态学梯度

3.1.1 开运算

先腐蚀再膨胀

 3.1.2 闭运算

先膨胀再腐蚀

 3.1.3 形态学梯度

膨胀结果减去腐蚀结果

 3.1.4 顶帽与黑帽运算

原图像减去开运算

 闭运算减去原图像

 

3.2 相关函数

 

//形态学应用
int test3()
{
	//用于验证形态学应用的二值化矩阵
	Mat src = (Mat_<uchar>(9, 12) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0,
		0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

	namedWindow("src", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("src", src);

	//3×3矩形结构元素
	Mat kernel = getStructuringElement(0, Size(3, 3));

	//对二值化矩阵进行形态学操作
	Mat open, close, gradient, tophat, blackhat, hitmiss;

	//对二值化矩阵进行开运算
	morphologyEx(src, open, MORPH_OPEN, kernel);
	namedWindow("open", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("open", open);

	//对二值化矩阵进行闭运算
	morphologyEx(src, close, MORPH_CLOSE, kernel);
	namedWindow("close", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("close", close);

	//对二值化矩阵进行梯度运算
	morphologyEx(src, gradient, MORPH_GRADIENT, kernel);
	namedWindow(" gradient", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("gradient", gradient);

	//对二值化矩阵进行顶帽运算
	morphologyEx(src, tophat, MORPH_TOPHAT, kernel);
	namedWindow("tophat", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("tophat ", tophat);

	//对二值化矩阵进行黑帽运算
	morphologyEx(src, blackhat, MORPH_BLACKHAT, kernel);
	namedWindow("blackhat", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("blackhat", blackhat);

	//对二值化矩阵进行击中击不中变换
	morphologyEx(src, hitmiss, MORPH_HITMISS, kernel);
	namedWindow("hitmiss", WINDOW_NORMAL);//可以自由调节显示图像的尺寸
	imshow("hitmiss", hitmiss);


	cout << "用图像验证形态学操作效果" << endl;
	waitKey(0);

	Mat keys = imread("F:/testMap/key.png", IMREAD_GRAYSCALE);
	imshow("原图像", keys);

	threshold(keys, keys, 80, 255, THRESH_BINARY); //二值化
	imshow("二值化后的keys", keys);

	//5×5矩形结构元素
	Mat kernel_keys = getStructuringElement(0, Size(5, 5));
	Mat open_keys, close_keys, gradient_keys, tophat_keys, blackhat_keys, hitmiss_keys;

	//对图像进行开运算
	morphologyEx(keys, open_keys, MORPH_OPEN, kernel_keys);
	imshow("open_keys", open_keys);

	//对图像进行闭运算
	morphologyEx(keys, close_keys, MORPH_CLOSE, kernel_keys);
	imshow("close_keys", close_keys);

	//对图像进行梯度运算
	morphologyEx(keys, gradient_keys, MORPH_GRADIENT, kernel_keys);
	imshow(" gradient_keys", gradient_keys);

	//对图像进行顶帽运算
	morphologyEx(keys, tophat_keys, MORPH_TOPHAT, kernel_keys);
	imshow("tophat_keys", tophat_keys);

	//对图像进行黑帽运算
	morphologyEx(keys, blackhat_keys, MORPH_BLACKHAT, kernel_keys);
	imshow("blackhat_keys", blackhat_keys);

	//对图像进行击中击不中变换
	morphologyEx(keys, hitmiss_keys, MORPH_HITMISS, kernel_keys);
	imshow("hitmiss_keys", hitmiss_keys);

	waitKey(0);
	return 0;
}

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

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

相关文章

[工业互联-22]:常见EtherCAT主站方案:Acontis公司的商用Windows 解决方案

目录 前言&#xff1a;非实时、纯软件解决方案 1.1 概述 1.2 缺点 1.3 实时性思路 方案1&#xff1a;非实时性能的解决方案&#xff1a;etherCAT优化网卡驱动程序 方案2&#xff1a;EtherCAT内核调度模块EcatDrv 方案3&#xff1a;具有硬实时性能的解决方案&#xff1a;…

【C++】C++创建动态链接库并调用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#x1f95e; 文章目…

车载蓝牙通信开发之各种协议原理解析

车载蓝牙开发需要考虑到蓝牙协议栈集成、连接管理、电话功能集成、媒体播放控制、数据交换和服务发现、安全性和隐私保护等方面。这对于实现车辆与蓝牙设备之间的无线通信和交互功能非常关键。 使车辆能够与蓝牙设备进行通信和交互的开发过程。 蓝牙协议栈集成&#xff1a; …

SpringCloud与SpringBoot版本对应关系

浏览器访问start.spring.io/actuator/info 出现JSON字符串&#xff0c;再访问json.cn&#xff0c;在里面解析该字符串 如果对应不上&#xff0c;可能会出现很多环境上的坑

KKRT16 PSI算法

概念介绍 KKRT16 算法是一种基于OT的轻量级隐私求交协议&#xff0c;用于在半诚实敌手存在的情况下对伪随机函数&#xff08;OPRF&#xff09;进行不经意的评估。 在 OPRF 协议中&#xff0c;接收器有一个输入 r r r&#xff1b; 发送方获得输出 s s s&#xff0c;接收方获得…

【Hello mysql】 mysql的基本查询

Mysql专栏&#xff1a;Mysql 本篇博客简介&#xff1a;介绍mysql的基本查询 mysql的基本查询 create单行插入全列插入多行查询指定列查询插入否则更新 &#xff08;不常用&#xff09;替换 Retrieveselect列全列查询指定列查询查询字段为表达式结果去重 where条件找到英语小于6…

Unity 分块延迟渲染01 (TBDR)

现代移动端图形体系结构的概述 现代SoC通常会同时集成CPU和GPU。 CPU被用于处理需要低内存延迟的序列、大量分支的数据集&#xff0c;其晶体管用于流控制和数据缓存。 GPU为处理大型&#xff0c;未分支的数据集&#xff0c;如3D渲染。晶体管专用于寄存器和算术逻辑单元&…

Django_内置的用户认证系统

目录 一、用户对象 1. 创建用户 2. 修改密码 3. 用户验证 二、权限与授权 1. 默认权限 2. 用户组 3. 在代码中创建权限 4. 权限缓存 三、在视图中认证用户 1、登录用户 2、注销用户 3、用户登录的访问限制 3.1、原始的办法 3.2、函数视图使用login_required装饰…

【前端】网页开发精讲与实战 CSS Day 1

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;前端 &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对你有…

Go 并发模型—Goroutine

前言 Goroutines 是 Go[1] 语言主要的并发原语。它看起来非常像线程&#xff0c;但是相比于线程它的创建和管理成本很低。Go 在运行时将 goroutine 有效地调度到真实的线程上&#xff0c;以避免浪费资源&#xff0c;因此您可以轻松地创建大量的 goroutine&#xff08;例如每个请…

快速排序—C语言实现

目录 前言 快速排序 实现逻辑 1. hoare版本​编辑 2. 挖坑法 3. 前后指针版本 快速排序优化 1. 三数取中法选key 2. 递归到小的子区间时&#xff0c;可以考虑使用插入排序 快速排序非递归&#xff08;用栈实现&#xff09; 快速排序的特性总结 全部代码 前言 &#…

idea-spring boot开发

安装maven与配置配置maven安装插件 已经装好了idea与jdk 安装maven与配置 下载地址: https://maven.apache.org/download.cgi 下载合适的版本 配置maven 打开设置: 直接搜索 :maven 配置变量: 此电脑->属性->高级系统设置->环境变量 新建系统变量 MAVEN_HOME&#xff…

Web安全——渗透测试基础知识下

渗透测试基础 Web安全一、VMware虚拟机学习使用1、虚拟机简单介绍2、网络模式2.1 桥接网络&#xff08;Bridged Networking&#xff09;2.2 NAT模式2.3 Host-Only模式 3、通俗理解 二、Kali的2021安装与配置1、简单介绍2、Kali的版本3、配置3.1 安装虚拟机open-vm-tools-deskto…

基于matlab从ROI和蒙版在图像中创建标记(附源码)

一、前言 此示例演示如何从一组 ROI 创建标记的阻止映像。 在此示例中&#xff0c;您使用两种方法来获取和显示标记的数据。一种方法使用多边形ROI对象来存储肿瘤和正常组织区域边界的坐标。该函数将ROI坐标转换为标记的块图像。第二种方法使用掩码来指示图像的二进制分割为组…

能不能推荐个 vue 后台管理系统模板?

前言 下面是我整理的vue2和vue3的一些后台管理系统模板&#xff0c;希望对你有帮助~ Vue2 1、iview-admin Star: 16.4k 基于 iview组件库开发的一款后台管理系统框架&#xff0c;提供了一系列的强大组件和基础模板&#xff0c;方便开发人员快速搭建一套功能丰富、界面美观、…

web入门案例-部门篇

开发流程 完成对应部门管理和员工管理的需求 准备工作 注意&#xff1a;service还要写接口实体类&#xff0c;mapper只写接口即可&#xff0c;controller是实体类 对应的三个注解 RestController&#xff08;方法返回值作为响应值&#xff09; Mapper(控制反转IOC&#xff0c…

漏洞深度分析 | CVE-2023-36053-Django 表达式拒绝服务

​ 项目介绍 Django 是一个高级 Python Web 框架&#xff0c;鼓励快速开发和简洁、务实的设计。它由经验丰富的开发人员构建&#xff0c;解决了 Web 开发的大部分麻烦&#xff0c;因此您可以专注于编写应用程序&#xff0c;而无需重新发明轮子。它是免费且开源的。 项目地址…

CodeTop整理-树篇

目录 103. 二叉树的锯齿形层次遍历 236. 二叉树的最近公共祖先 124. 二叉树中的最大路径和 102. 二叉树的层序遍历 94. 二叉树的中序遍历 110. 平衡二叉树 572. 另一个树的子树 96. 不同的二叉搜索树 543. 二叉树的直径 297. 二叉树的序列化与反序列化 199. 二叉树的…

eNSP-VRRP虚拟路由器冗余技术

VRRP-虚拟路由器冗余技术 文章目录 VRRP-虚拟路由器冗余技术一、拓扑结构二、基本配置三、测试验证四、知识点详解1.VRRP路由器2.报文格式3.工作过程 一、拓扑结构 二、基本配置 R1: #配置ip <Huawei>sys [Huawei]sys r1 [r1]int g0/0/0 [r1-GigabitEthernet0/0/0]ip a…

快速排序算法!

快速排序 什么是快速排序&#xff08;quickSort&#xff09;&#xff1f; 主要分成两部分实现&#xff0c;分区、递归操作。 分区 从数组中任意选择一个 “基准”&#xff0c;所有比基准小的元素放在基准前面&#xff0c;比基准大的元素放在基本后面。 递归 递归地对基准…