【Emgu CV教程】10.14、ConnectedComponents()函数计算连通区域

news2024/11/25 23:00:43

文章目录

  • 一、概念
    • 1.什么叫图像的连通区域
    • 2.提取连通区域的函数
  • 二、简单应用
    • 1.原始素材
    • 2.代码
    • 3.运行结果
    • 4.连通区域上色


一、概念

1.什么叫图像的连通区域

图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来。

最简单的理解:灰度图中,黑色背景值为0,前景多是大于0的,当有一片区域值相同,而且像素点彼此相连,就是一个连通区域。比如下面这张图(默认是二值化图形),就有7个连通区域,分别是字母E、m、g、u、C、V和符号"."
在这里插入图片描述
它有什么用呢,经常进行算法设计的同学们应该能够理解,在图像分割、目标检测、形状分析都能用的到。

2.提取连通区域的函数

Emgu.CV中提取连通区域的函数是:

public static ConnectedComponentsWithStats
(
	IInputArray image, // 输入图像
	IOutputArray labels, // 输出标记图像,与输入图像大小一样,对应的联通区域会标记上对应的数字0为背景,其它数字为对应的联通区域
	IOutputArray stats, // 每一连通域的信息,表示每个连通区域的外接矩形(起始点的x、y、宽和高)和面积
	IOutputArray centroids, // 连通区域的中心点
	LineType connectivity = LineType.EightConnected, // 线形
	DepthType labelType = DepthType.Cv32S, // 输出标记图像的类型
	ConnectedComponentsAlgorithmsTypes cclType = ConnectedComponentsAlgorithmsTypes.Default
)

函数返回的是一个int类型数值,代表有几个连通区域。

二、简单应用

1.原始素材

原始素材srcMat如下图:
在这里插入图片描述
图像宽737,长349。

2.代码

代码如下:

Mat tempMat = srcMat.Clone();
Mat dstMat = srcMat.Clone();
Mat gray = new Mat();
int threshold = 40;

// 1.转换图像
CvInvoke.CvtColor(tempMat, gray, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(gray, gray, threshold, 255, ThresholdType.Binary);

// 2.利用ConnectedComponentsWithStats计算连通区域参数
Mat labels = new Mat(); // 对原始图中的每一个像素都打上标签,背景为0,连通域打上1,2,3。。。的标签,同一个连通域的像素打上同样的标签。相当与对每一个像素进行了分类(分割)
var stats = new Mat(); // 每一连通域的信息,表示每个连通区域的外接矩形(起始点的x、y、宽和高)和面积
var centroids = new Mat(); // 连通区域的中心点

int a = CvInvoke.ConnectedComponentsWithStats(gray, labels, stats, centroids, LineType.EightConnected, DepthType.Cv16U);
Int32[,] intStatus = (Int32[,])stats.GetData(); // x,y,width,height,area四个参数有可能超过255,所以要转换成int32数组,不能转成Image<Gray, byte> img

3.运行结果

运行结果:
int a = 8;
Int32[,] intStatus如下所示:
在这里插入图片描述
a是代表连通区域个数,应该是7个,为什么结果是8呢???请看intStatus[0, 0]、intStatus[0, 1]、intStatus[0, 2]、intStatus[0, 3]的值,它代表了第0个连通区域的外接矩形,从左上角的[0,0]点开始,宽度737,长度349。intStatus[0, 4]好像是代表外接矩形面积,它不就是原始图片的尺寸吗??所以Int32[,] intStatus得出来的矩形组合,第一个不能用,其余的才是。

intStatus[1, 0]、intStatus[1, 1]、intStatus[1, 2]、intStatus[1, 3]代表从点[503,123]开始,宽度90,长度108的矩形,读者们可以试一试,它其实框起来的是字母C。

4.连通区域上色

根据网上最流行的说法,连通区域找到以后,最简单的一个应用就是给不同的区域上色,找连通区域的代码就是上面的,上色的代码就更简单了,如下:


// 接上面的连通区域查找
List<int[]> listColors = new List<int[]>();
Random random = new Random(); // 定义一个随机类的对象,目的是每个连通区域都有不同的颜色
for (int i = 0; i < a; i++)
{
    int[] color = new int[] { random.Next(0, 255), random.Next(0, 255), random.Next(0, 255) };
    listColors.Add(color);
}

// 以不同颜色标记出不同的连通域
Mat result = new Mat(tempMat.Size, DepthType.Cv8U, 3);
result.SetTo(new MCvScalar(0, 0, 0));
Image<Bgr, int> img = result.ToImage<Bgr, int>();

Int16[,] intLabels = (Int16[,])labels.GetData();
int w = result.Cols;
int h = result.Rows;
for (int i = 0; i < h; i++)
{
    for (int j = 0; j < w; j++)
    {
        int label = intLabels[i, j];
        if (label == 0 || label >= listColors.Count) // 背景的黑色不改变
        {
            continue;
        }

        img.Data[i, j, 0] = listColors[label][0];
        img.Data[i, j, 1] = listColors[label][1];
        img.Data[i, j, 2] = listColors[label][2];
    }
}

result = img.Mat;
result.ConvertTo(result, DepthType.Cv8U);

CvInvoke.Imshow("gray, " + gray.Size.ToString(), gray);
CvInvoke.Imshow("Final result image, " + result.Size.ToString(), result);

这里注意的就是这句话:

Int16[,] intLabels = (Int16[,])labels.GetData();

labels是连通区域查找中,返回的标签记号,也就是这个函数

int a = CvInvoke.ConnectedComponentsWithStats(gray, labels, stats, centroids, LineType.EightConnected, DepthType.Cv16U);

它的大小就是图像大小,作用就是对像素的每一个像素都打上标签,背景为0,连通域打上1,2,3… …,同一个连通域的像素打上同样的标签。相当与对每一个像素进行了分类,利用这个值,遍历图像的时候,判断它的值是多少,就在listColors中选择对应颜色。最终实现原始图像连通区域上色。效果如下:
在这里插入图片描述


原创不易,请勿抄袭。共同进步,相互学习。

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

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

相关文章

韩顺平0基础学java——第19天

p396-406 final关键字 1.final修饰的为“常量”&#xff0c;需要给初始值。1可以直接定义时赋值&#xff0c;2在构造器中&#xff0c;3在代码块中。 注意静态代码块只能访问静态变量。 2.如果final修饰的关键字是静态的&#xff0c;那就不能在构造器中赋值&#xff0c;只能…

2024年最新Microsoft Edge关闭自动更新的方法分享

这里写自定义目录标题 打开【服务】 打开【服务】 windows中搜索服务&#xff0c;如下图&#xff1a; 打开服务界面&#xff0c;找到“Microsoft Edge Update Service (edgeupdate)” 及 “Microsoft Edge Update Service (edgeupdatem)” 两个服务&#xff0c;设置为禁用

C++ | Leetcode C++题解之第132题分割回文串II

题目&#xff1a; 题解&#xff1a; class Solution { public:int minCut(string s) {int n s.size();vector<vector<int>> g(n, vector<int>(n, true));for (int i n - 1; i > 0; --i) {for (int j i 1; j < n; j) {g[i][j] (s[i] s[j]) &…

人工智能--教育领域的运用

文章目录 &#x1f40b;引言 &#x1f40b;个性化学习 &#x1f988;体现&#xff1a; &#x1f988;技术解析&#xff1a; &#x1f40b;智能辅导与虚拟助手 &#x1f988;体现&#xff1a; &#x1f988;技术解析&#xff1a; &#x1f40b;自动评分与评估 &#x1f…

【嵌入式】波特率9600,发送8个字节需要多少时间,如何计算?

问题&#xff1a; 波特率9600&#xff0c;发送 01 03 00 00 00 04 44 09 (8字节) 需要多少时间&#xff0c;如何计算&#xff1f; 在计算发送数据的时间时&#xff0c;首先要考虑波特率以及每个字符的数据格式。对于波特率9600和标准的UART数据格式&#xff08;1个起始位&…

Jenkins+Rancher2.7部署构建

在Jenkins中使用rancher插件时需要去查找工作负载地址 在Rancher2.7没有查看Api按钮了需要自己去查找 1.进入https://192.168.x.xx:6443/v3/projects/ 2.输入在rancher中要查找的的项目名称并点击deployment连接进入下一个页面 3.找到自己的deployment随便点一个进去 4.浏览…

【安装笔记-20240608-Linux-免费空间之三维主机免费空间】

安装笔记-系列文章目录 安装笔记-20240608-Linux-免费空间之三维主机免费空间 文章目录 安装笔记-系列文章目录安装笔记-20240608-Linux-免费空间之三维主机免费空间 前言一、软件介绍名称&#xff1a;三维主机免费空间主页官方介绍 二、安装步骤测试版本&#xff1a;openwrt-…

Day53 动态规划part12

LC309买卖股票的最佳时机含冷冻期 与LC122类似&#xff0c;都是可无限次购买股票&#xff0c;只不过引入了冷冻期的概念dp[i][0] 第i天持有股票收益&#xff1b;dp[i][1] 第i天不持有股票收益;情况一&#xff1a;第i天是冷静期&#xff0c;不能以dp[i-1][1]购买股票,所以以dp[…

10-指针进阶——char型,多级指针,void指针,const指针

10-指针进阶——char型&#xff0c;多级指针&#xff0c;void指针&#xff0c;const指针 文章目录 10-指针进阶——char型&#xff0c;多级指针&#xff0c;void指针&#xff0c;const指针一、char 型指针1.1 示例 二、多级指针2.1 示例 三、 指针的万能拆解方法3.1 示例 四、v…

并查集进阶版

过关代码如下 #define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> #include<unordered_set> using namespace std;int n, m; vector<int> edg[400005]; int a[400005], be[400005]; // a的作用就是存放要摧毁 int k; int fa[400005]; int daan[400005]…

Qt OPC UA初体验

介绍 OPC UA全称Open Platform Unified Architecture&#xff0c;开放平台统一架构&#xff0c;是工业自动化领域通用的数据交换协议&#xff0c;它有两套主要的通信机制&#xff1a;1.客户端-服务器通信&#xff1b;2.发布订阅。Qt对OPC UA通信标准也提供了支持&#xff0c;目…

分享一个 .NET Core Console 项目使用依赖注入的详细例子

前言 依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&#xff09;是一种软件设计模式&#xff0c;主要用于管理和组织一个软件系统中不同模块之间的依赖关系。 在依赖注入中&#xff0c;依赖项&#xff08;也称为组件或服务&#xff09;不是在代码内部创建或查…

移动端投屏到大屏幕的操作详解

如果你懒得折腾电脑、电视或其他大屏设备上的影视软件安装及配置&#xff0c;可以选择直接在手机端上将影片投屏到电脑、电视或其他大屏设备上&#xff0c;这里给大家分享三种手机投屏的方法。 系统自带的投屏功能 不管是安卓、鸿蒙还是苹果操作系统&#xff0c;都自带了无线…

HTML静态网页成品作业(HTML+CSS)—— 24节气立夏介绍网页(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

最小相位系统

最小相位系统 1、传递函数 一个线性系统的响应。 比如一个RC低通滤波器&#xff1a; 交流分量在电容的充放电中被滤除掉&#xff0c;通过设置电容器的电容值&#xff0c;以及电阻值&#xff0c;能够控制这种滤除能力&#xff0c;这个参数为RC。 电容的电抗为 1 / j w C 1/j…

变声器软件免费版有哪些?国内外12大热门变声器大盘点!(新)

变声软件是一种人工智能AI音频处理工具&#xff0c;允许用户实时修改自己的声音或改变预先录制的音频。这些软件解决方案可提供不同的效果&#xff0c;如改变声音的音调或速度&#xff0c;或将我们的声音转换成其他人或其他东西的声音&#xff0c;如名人、卡通人物、机器人或不…

力扣96 不同的二叉搜索树 Java版本

文章目录 题目描述代码 题目描述 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5 示例 2&#xff1a; 输入…

澳大利亚和德国媒体投放-国外新闻发稿-海外软文推广

德国媒体 Firmenpresse德国新闻 Firmenpresse德国新闻是一家备受欢迎的新闻发布平台&#xff0c;其好友搜索引擎在收录网站方面表现出色。如果您希望更好地将您的新闻传播给德国受众&#xff0c;Firmenpresse德国新闻将是一个理想的选择。 Frankfurt Stadtanzeiger法兰克福城…

三维重建 虚拟内窥镜(VE)是什么?怎么实现 使用场景

1.虚拟内窥镜&#xff1a; 就是利用计算机图形学、虚拟现实、图像处理和科学可视化等信息处理技术仿真光学内窥镜对病人进行诊断的一种技术。 VE(Virtual Endoscopy)&#xff0c;虚拟内镜技术。这种CT重建图像可以模拟各种内镜检查的效果&#xff0c;它是假设视线位于所要观察…

RaspAP:轻松实现树莓派无线 AP

RaspAP 是一个可以将树莓派轻松部署成无线 AP&#xff08;Access Point&#xff09;的软件方案&#xff0c;具有一套响应式的 WebUI 来控制 WiFi&#xff0c;用起来和家用路由器一样方便。RaspAP 可以运行在 Raspbian 上&#xff0c;只需要先给树莓派安装好 Raspbian 系统&…