opencv#35 连通域分析

news2024/11/18 23:30:45

连通域分割原理

像素领域介绍:

4邻域是指中心的像素与它邻近的上下左右一共有4个像素,那么称这4个像素为中心像素的4邻域。

8邻域是以中心像素周围的8个像素分别是上下左右和对角线上的4个像素。

连通域的定义(分割)分为两种:以4邻域为相邻判定条件的连通域分割和8邻域为判定条件的连通域分割。连通域指某个区域内所有像素是相邻的,如果一个像素不能够通过这个区域中的像素到达另一个像素,那么这两个像素就不再同一连通域内。

连通域的划分通常采用两遍法,在进行连通域分析的时候,我们往往先对图像进行二值化处理,确定连通域的判定标准是采用4邻域还是8邻域,然后先对图像进行遍历得到结果,然后再对此结果进行遍历得到最终结果。

在进行遍历时遇到非0(非黑)的像素值,就对此像素进行编号,例如上图,进行第一次遍历时,遇到黄色的方格,标记为1,之后凡是与此放个相邻的像素,都将其设置为1,第一行遍历完后,赋值了1个1,遍历第二行,最左侧有个黄色像素,此像素的上方和左方的像素若有标记的数值,那么就将这个黄色像素标记为上方与左方数值较小的数,这里可以看到上方为空,左方是边缘,因此这个像素没有办法借助上方和左方标记,我们就需要对其进行独立标记,由于1已经用过,我们将其标记为2。

然后看下一个黄色的像素,这个像素左边的像素被标记为2,而上方是一个没有被标记的像素,因此这个像素也被标记为2。

然后继续看下一个像素,这个像素的左方和上方都被标记了,而两者标记数值不一致,因此我们根据规则选择两者之间较小数值,即1。

到达第三行时,遇见黄色像素,因为此像素上方的像素为1,因此也要记为1。

来到第四行,第四行第一个像素,左侧和上方都没有被标记,因此需要进行独立标记,1和2都用过了,我们对此像素标记3 。

下一个像素左侧为3上方为1,标记为1。

最后一行分别被标记为3和1。

 zhe

这样完成了第一次遍历,第二次遍历,将两个邻近的结果进行统一,比如上图第二行,标记为2和标记1的像素相连,因此我们将其中的2全部置为1,下方像素同理。 

这样便完成了两遍法实现图像邻域分割,图像分割的结果通过示例中也可以看出是一个与原图像具有相同尺寸的图像 。

只分割连通域的函数

connectedComponents()

int cv::connectedComponents(InputArray    image,
                             OutputArray   labels,
                                           connectivity =
                             int           8,
                             int           Itype = CV_325
                            )

·image:待标记不同连通域的图像单通道,数据类型必须为CV_8U。上面说过图像通常会进行二值化处理,若不进行二值化,则会将1~255之间的任何数都独立的看成不同区域,也就是即使出现2,3,4相邻的区域,也会判断为3个不同的连通域,因此,我们最好是使用0~255的数据,这样的数据是有限的,若我们使用0~1之间的小数,分割形式是无限的,那么分割的结果就会出现每一个单独的像素都是一个单独的连通域。我们要先对图像进行二值化,因为图像可能会受到光照影响,即使在真实物理世界中,是同一个像素值的物体,通过相机的采集,也会出现不同像素值的情况。

·labels:标记不同连通域后的输出图像,与输入图像具有相同尺寸。

·connectivity:标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域,默认参数为8.

·ltype:输出图像的数据类型,目前支持CV_32S和CV_16U两种数据类型,默认参数为CV_32S。

分割并统计连通域信息的函数

connectedComponentsWithStats()

void cv::connectedComponentsWithStats(InputArray    images,
                                      OutputArray   labels,
                                      OutputArray   stats,
                                      OutputArray   centroids,
                                                    connectiviity =
                                      int           8,
                                      int           ltype = cv_32s
                                     )

·image:待标记不同连通域的图像单通道,数据类型必须为CV_8U。

·labels:标记不同连通域后的输出图像,与输入图像具有相同的尺寸。

·stats:不同连通域的统计信息矩阵,矩阵的数据类型为CV_32S。矩阵中第i行是标签为i的连通域的统计特性。

·centroids:每个连通域的质心坐标,数据类型为CV_64F。

·connectivity:标记连通域时使用的邻域种类,4表示4-邻域,8表示8-邻域,默认参数为8。

·ltype:输出图像的数据类型,目前支持CV_32S和CV_16U两种数据类型,默认参数为CV_32S。

上图参数是此函数可以获得的信息。

示例 
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

using namespace cv; //opencv的命名空间
using namespace std;

//主函数
int main()
{
	//对图像进行距离变换
	Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/hua.jpg");
	if (img.empty())
	{
		cout << "请确认图像文件名是否正确" << endl;
		return -1;
	}
	Mat hua, huaBW;

	//将图像转成二值化的图像,用于统计连通域。
	cvtColor(img, hua, COLOR_BGR2GRAY);
	threshold(hua, huaBW, 25, 255, THRESH_BINARY); //二值化

	//生成随机颜色,用于区分不同连通域。
	RNG rng(10086); //RNG用来生成随机数,这里用了10086进行初始化。
	Mat out;
	int number = connectedComponents(huaBW, out, 8, CV_16U); //统计图像中连通域的个数
	vector<Vec3b> colors; //vector是一个能够存放任意类型的动态数组,Vec3b可以看成vector<uchar,3>,即一个uchar类型,长度为3的vector向量(简单地说,就是一个uchar类型的数组,长度为3).
	for (int i = 0; i < number; i++);
	{
		//使用均匀分布的随机数确定颜色;rng.uniform(),可以生成指定范围的均匀分布的随机数
		Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		colors.push_back(vec3);
	}
	 //以不同的颜色标记出不同的连通域
	Mat result = Mat::zeros(hua.size(), img.type());
	int w = result.cols;
	int h = result.rows;
	for (int row = 0; row < h; row++)
	{
		for (int col = 0; col < w; col++)
		{
			int label = out.at<uint16_t>(row, col);
			if (label == 0) //背景的黑色不改变
			{
				continue;
			}
			result.at<Vec3b>(row, col) = colors[label];
		}
	}

	//显示结果
	imshow("原图", img);
	imshow("标记后的图像", result);

	cout <<"接下来统计连通域信息"<< endl;
	waitKey(0);

	Mat stats, centroids;
	number = connectedComponentsWithStats(huaBW, out, stats, centroids, 8, CV_16U);
	vector<Vec3b> colors_new;
	for (int i = 0; i < number; i++)
	{
		//使用均匀分布的随机数确定颜色
		Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		colors_new.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);
		int area = stats.at<int>(i, CC_STAT_AREA);

		//中心位置绘制
		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_new[i], 1, 8, 0);
		putText(img, format("%d", i), Point(center_x, center_y),FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);
		cout << "number" << i << ",aera:" << area << endl;
	}
	//显示结果
	imshow("标记后的图像", img);
	waitKey(0);//等待函数用于显示图像,按下键盘任意键后退出
	return 0;

}

原图:

结果 

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

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

相关文章

C++笔记之RTTI、RAII、MVC、MVVM、SOLID在C++中的表现

C++笔记之RTTI、RAII、MVC、MVVM、SOLID在C++中的表现 —— 杭州 2024-01-28 code review! 文章目录 C++笔记之RTTI、RAII、MVC、MVVM、SOLID在C++中的表现1.RTTI、RAII、MVC、MVVM、SOLID简述2.RAII (Resource Acquisition Is Initialization)3.RTTI (Run-Time Type Informat…

steam幻兽帕鲁服务器配置费用报价,4核16G

幻兽帕鲁服务器价格多少钱&#xff1f;4核16G服务器Palworld官方推荐配置&#xff0c;阿里云4核16G服务器32元1个月、96元3个月&#xff0c;腾讯云换手帕服务器服务器4核16G14M带宽66元一个月、277元3个月&#xff0c;8核32G22M配置115元1个月、345元3个月&#xff0c;16核64G3…

某度Pan复活,突破限速,很强大!

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; 作为国内领先的云存储服务提供商之一&#xff0c;某度Pan为用户提供了一个便捷的文件存储和分享平台。然而&#xff0c;用户普遍反映某度Pan的下载速…

简盒工具箱iapp源码

一款工具箱兼做软件库。 新增远程更新功能 修复了部分失效功能 修复了偶尔会卡在启动页的情况 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88776737 更多资源下载&#xff1a;关注我。

漏洞原理MySql注入 Windows中Sqlmap 工具的使用

漏洞原理MySql注入 SQLmap是一款开源的自动化SQL注入工具&#xff0c;用于检测和利用Web应用程序中的SQL注入漏洞。以下是SQLmap工具的使用总结&#xff1a; 安装和配置&#xff1a;首先需要下载并安装SQLmap工具。安装完成后&#xff0c;可以通过命令行界面或图形用户界面来使…

2024幻兽帕鲁服务器,阿里云配置

阿里云幻兽帕鲁服务器Palworld服务器推荐4核16G配置&#xff0c;可以选择通用型g7实例或通用算力型u1实例&#xff0c;ECS通用型g7实例4核16G配置价格是502.32元一个月&#xff0c;算力型u1实例4核16G是432.0元/月&#xff0c;经济型e实例是共享型云服务器&#xff0c;价格是32…

案例分享:长沙红胖子公司内部评估高清内窥镜功能列表流程产出成果鉴赏

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/135898723 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

多地多活与单元化架构

多地多活与单元化架构 背景 在业务发展到一定阶段之后&#xff0c;任何因故障而导致的服务中断都会带来巨大的损失。为了提高系统的伸缩能力与高可用能力&#xff0c;我们都不断的在努力消除系统单点瓶颈。如使用应用集群是为了解决服务层的单点问题&#xff0c;使用主从数据…

FreeRTOS任务知识详解

前言 本篇文章旨在记录我学习FreeRTOS实时操作系统中&#xff0c;有关于Free RTOS的任务知识的记录。由于RTOS系统的核心就是任务管理&#xff0c;而且我们大多数人学习RTOS的初衷就是为了使用RTOS的多任务处理功能&#xff01; 初步上手RTOS首先应该掌握的就是任务的创建、删除…

AlmaLinux上安装Docker

AlmaLinux上安装Docker 文章目录 AlmaLinux上安装Docker一、前言二、具体步骤1、Docker 下载更新系统包索引&#xff1a;添加Docker仓库&#xff1a;安装Docker引擎&#xff1a; 2、Docker服务启动启动Docker服务&#xff1a;设置Docker开机自启&#xff1a; 3、Docker 安装验证…

GitLab16.8配置webhooks、Jenkins2.4配置GitLab插件实现持续集成、配置宝塔面板实现持续部署

看本篇文章的前提是已经部署完GItlab和Jenkins服务器&#xff0c;已经可以手动构建成功&#xff0c;并且经过了很多次实践&#xff0c;对这两款软件基本熟悉。 建议大家按以下顺序看 前端自动化&#xff08;其一&#xff09;部署gitlab https://blog.csdn.net/weixin_45062076…

数据中心代理IP:最优性价比业务应用指南

数据中心代理IP在应对高速高并发的业务时&#xff0c;以独特的高速传输&#xff0c;游刃有余地应对多任务处理&#xff0c;适合于特定业务场景的高效加速。理性选用数据中心代理IP&#xff0c;可以为业务将迎来更加稳健和迅速的发展。今天&#xff0c;我们将揭示数据中心代理IP…

QT+VS实现Kmeans++

1、Kmeans的原理如下&#xff1a; &#xff08;1&#xff09;首先选取样本中任一数据点作为第一个聚类中心&#xff1b; &#xff08;2&#xff09;计算样本每一个数据点至现所有聚类中心的最近距离&#xff0c;并记录下来&#xff1b; &#xff08;3&#xff09;逐一挑选所…

ATT汇编

指令后缀 AT&T格式的汇编指令有不同的后缀 其中 b表示byte&#xff0c;字节 w表示word&#xff0c;字/两字节 l表示long&#xff0c;32位系统下的long是4字节 q表示quad&#xff0c;意味四重&#xff0c;表示4个字/8字节 寄存器用途 参见 AT&T的汇编世界 - Gemfield…

备战蓝桥杯----数据结构及STL应用(基础2)

上次我们讲了vector的大致内容&#xff0c;接下来让我们讲一下栈&#xff0c;队列吧&#xff01; 什么是栈呢&#xff1f; 很简单&#xff0c;我们用的羽毛球桶就是&#xff0c;我们取的球&#xff0c;是最后放的&#xff0c;栈是一种先进后出的数据结构。 方法函数 s.push(…

Dubbo框架注册中心-Zookeeper搭建

Dubbo 是阿里巴巴公司开源的高性能、轻量级的Java RPC框架&#xff0c;致力于提供高性能。 Dubbo官网 本篇开始dubbo的第一篇&#xff0c;注册中心 ZooKeeper 环境搭建。 环境前置&#xff1a;由于Zookeeper是基于Java环境&#xff0c;必须安装有JDK。查看命令 java -version。…

蓝桥杯---九数组分数

1,2,3 ... 9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码。 注意,只能填写缺少的部分,不要重复抄写已有代码。不要填写任何多余的文字。 代码 public class _05九数组分数 {public static void test(int[] x){int a …

在WebSocket中使用Redis出现空指针异常解决方案

文章目录 在WebSocket中使用Redis1.问题描述2.原因3.解决步骤1.新建一个SpringUtil.java类&#xff0c;通过getBean的方法主动获取实例2.在WebSocketSingleServer.java中导入 在WebSocket中使用Redis 1.问题描述 在controller 和 service中都可以正常使用Redis&#xff0c;在…

03_Opencv简单实例演示效果和基本介绍

视频处理 视频分解图片 在后面我们要学习的机器学习中,我们需要大量的图片训练样本,这些图片训练样本如果我们全都使用相机拍照的方式去获取的话,工作量会非常巨大, 通常的做法是我们通过录制视频,然后提取视频中的每一帧即可! 接下来,我们就来学习如何从视频中获取信息 ubun…

JVM工作原理与实战(三十):堆内存状况的对比分析

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、堆内存状况的对比分析 1.正常情况 2.异常情况&#xff08;内存泄漏&#xff09; 二、产生内存溢出的原因 总结 前言 JVM作为Java程序的运行环境&#xff0c;其负责解释和执行字…