OpenCV4(C++)—— 图像连通域的详细分析
文章目录
- 前言
- 一、connectedComponents函数
- 二、connectedComponentsWithStats函数
前言
图像连通域,其实就是图像分割的一种方法。它通过检测像素之间的连接关系和相似性来划分图像中的区域,以便进行后续处理。图像邻域和图像邻域分析就不介绍了,网上很多。本文会通过代码和结果图来直观展示。
一、connectedComponents函数
OpenCV4提供了提取图像中不同连通域的 connectedComponents() 函数,并为部分参数增加了默认值。使用时直接填入输入图像和输出图像两个参数即可。
举例:找出上面图像中所有水果,并用矩形框标出
代码如下(示例):
#include <opencv2/opencv.hpp>
#include<iostream>
using namespace std;int main()
{cv::Mat image = cv::imread("C:/Users/Opencv/temp/300.png", cv::IMREAD_GRAYSCALE);cv::Mat binImg;cv::threshold(image, binImg, 235, 255, cv::THRESH_BINARY_INV); // 二值化处理// //统计图像中连通域的个数cv::Mat labels;int numComponents = cv::connectedComponents(binImg, labels);// 绘制每个连通域的边界框cv::Mat output = image.clone();for (int i = 1; i < numComponents; ++i) {// 提取当前连通域的maskcv::Mat mask = (labels == i);// 查找轮廓std::vector<std::vector<cv::Point>> contours;cv::findContours(mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);// 绘制边界框cv::Rect boundingRect = cv::boundingRect(contours[0]);cv::rectangle(output, boundingRect, cv::Scalar(0, 255, 0), 2);}cv::imshow("原图", image);cv::imshow("二值图", binImg);cv::imshow("标记", output);cv::waitKey(0);cv::destroyAllWindows();return 0;
}
分析:
(1)根据图像邻域分析原理,进行连通域统计之前,要先把输入图像转换为二值图像。
(2)将二值图传入connectedComponents函数中,连通域结果记录在labels中,返回值是连通域的个数。可视化labels,白色区域就是函数判定的连通域,对这些连通域的所有像素会进行标号处理,从“1”开始。从图1中可以看到很许多较小的连通域,将其放大(如图2),可以看到标号“17”的连通域只有4个像素,标号“18”的只有2个像素。
(3)示例代码中 cv::Mat mask = (labels == i); 分析:当 i=1 时,labels图中只会把标号“1”的连通域提取出来,其他连通域都置为0,所以通过循环可依次找出不同标号的连通域。下面图3为标号“1”的连通域,可以看到其他白色区域都没有了。然后再对它进行查找轮廓,再添加矩形框,结果如图4。
下面图5为循环到标号“7”的连通域,详细像素值如图6,矩形框结果如图7
(4)示例代码的最终结果如图8。而原本只想要检测出三个水果,可以通过判定连通域大小,将较大的连通域删除,只保留较大的。示例代码修改如下,结果如图9所示
int main()
{cv::Mat image = cv::imread("C:/Users/Opencv/temp/300.png", cv::IMREAD_GRAYSCALE);cv::Mat binImg;cv::threshold(image, binImg, 235, 255, cv::THRESH_BINARY_INV); // 二值化处理// //统计图像中连通域的个数cv::Mat labels;int numComponents = cv::connectedComponents(binImg, labels);// 绘制每个连通域的边界框cv::Mat output = image.clone();for (int i = 1; i < numComponents; ++i) {// 提取当前连通域的maskcv::Mat mask = (labels == i);// 查找轮廓std::vector<std::vector<cv::Point>> contours;cv::findContours(mask, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // 计算边界框面积cv::Rect boundingRect = cv::boundingRect(contours[0]);int area = boundingRect.width * boundingRect.height;if (area < 200) // 面积小于200的不要continue;// 绘制边界框cv::rectangle(output, boundingRect, cv::Scalar(0, 255, 0), 2);}cv::imshow("原图", image);cv::imshow("二值图", binImg);cv::imshow("标记", output);cv::waitKey(0);cv::destroyAllWindows();return 0;
}
二、connectedComponentsWithStats函数
connectedComponents()函数只能通过标签将图像中的不同连通域区分开,无法得到更多的统计信息。上面的示例代码中,额外采用了findContours函数获得轮廓,然后使用boundingRect函数来计算其最小外接矩形。
因为得到目标的矩形区域是非常常用的一个步骤,所以OpenCV4提供了connectedComponentsWithStats ()函数用于标记出图像中不同连通域的同时统计连通域的位置、面积的信息。
相比于connectedComponents()函数,该函数主要多了两个参数:stats和centroids
int cv::connectedComponentsWithStats(InputArray image, // 输入图像,应为二值化图像OutputArray labels, // 输出标签图像,每个像素点对应一个连通域标签OutputArray stats, // 输出统计信息,包括连通域的外接矩形、面积等OutputArray centroids, // 输出连通域的质心坐标int connectivity = 8, // 连通性,可选择 4 或 8 连通int ltype = CV_32S // 标签图像的数据类型,默认为 CV_32S
);
上述示例代码可以修改为:
int main()
{cv::Mat image = cv::imread("C:/Users/Opencv/temp/300.png", cv::IMREAD_GRAYSCALE);cv::Mat binImg;cv::threshold(image, binImg, 235, 255, cv::THRESH_BINARY_INV); // 二值化处理// 连通组件标记及统计信息计算cv::Mat labels, stats, centroids;int numComponents = cv::connectedComponentsWithStats(binImg, labels, stats, centroids);// 绘制每个连通组件的外接矩形和质心cv::Mat output = image.clone();cv::cvtColor(output, output, cv::COLOR_GRAY2BGR); // 将灰度图转为伪彩色图以便绘制// cv::Mat output = cv::imread("C:/Users/jutze/ljw_C++/Opencv/temp/300.png"); // 或者直接用原图的彩色图for (int i = 1; i < numComponents; ++i) {// 根据面积过滤连通组件int area = stats.at<int>(i, cv::CC_STAT_AREA);if (area > 200){// 绘制外接矩形cv::Rect boundingRect(stats.at<int>(i, cv::CC_STAT_LEFT),stats.at<int>(i, cv::CC_STAT_TOP),stats.at<int>(i, cv::CC_STAT_WIDTH),stats.at<int>(i, cv::CC_STAT_HEIGHT));cv::rectangle(output, boundingRect, cv::Scalar(0, 255, 0), 2);// 绘制质心cv::Point centroid(centroids.at<double>(i, 0), centroids.at<double>(i, 1));cv::circle(output, centroid, 5, cv::Scalar(255, 0, 0), -1);}}cv::imshow("原图", image);cv::imshow("二值图", binImg);cv::imshow("标记", output);cv::waitKey(0);cv::destroyAllWindows();return 0;
}
注:示例代码中,有一行代码是将灰度图转为伪彩色图,我们知道灰度图是无法转回彩色图的,所以这步称为伪彩色。即将单通道转为三通道,但数值一样,如[247]转为[247,247,247]。三个通道数值一样,所呈现的视觉效果跟灰度图是相同的,如下图
可以看到,output已经是3×UINT8的三通道类型了,但看起来还是跟灰度图一样。再放大看看数值,三个通道一样
因为原图是彩色图,示例代码中将其转为灰度图,我们也可以直接用原图来进行绘制,结果如下
相关文章:

OpenCV4(C++)—— 图像连通域的详细分析
文章目录 前言一、connectedComponents函数二、connectedComponentsWithStats函数 前言 图像连通域,其实就是图像分割的一种方法。它通过检测像素之间的连接关系和相似性来划分图像中的区域,以便进行后续处理。图像邻域和图像邻域分析就不介绍了&#x…...

Rule-Engine-Starter V1.0.0
一个轻量级的规则引擎、搜索引擎,让条件匹配简单、优雅。 GIT地址 https://gitcode.cosmoplat.com/15011240224/rule-engine-starter 介绍 Rule-Engine-Starter 是一个轻量级规则引擎,V1.0.0主要解决条件匹配问题。比如飞书文档,每个文档都…...

绘制X-Bar-S和X-Bar-R图,监测过程,计算CPK过程能力指数
X-Bar-S图和X-Bar-R图是统计质量控制中常用的两种控制图,用于监测过程的稳定性和一致性。它们的主要区别在于如何计算和呈现数据的变化以及所关注的问题类型。 X-Bar-S图(平均值与标准偏差图): X-Bar代表样本均值,S代表…...

【每日一句】只出现一次的数
文章目录 Tag题目来源题目解读解题思路方法一:位运算 其他语言Cpython3 写在最后 Tag 【位运算-异或和】【数组】【2023-10-14】 题目来源 136. 只出现一次的数字 题目解读 给你一个数组,找出数组中只出现一次的元素。题目保证仅有一个元素出现一次&a…...

GDB调试程序常用命令
编译文件 g -g -o test test.cpp(注意:GDB调试的前提是在编译时加上-g参数.) 启动gdb # 方法一 gdb test # 方法二 gdb file test 设置断点 tbreak:设置临时断点,仅在第一次触发后失效。 watch:设置观察点,监控变量的…...

C语言,求两个数的二进制表达中,有多少个位数不同
以前我的博客中写过一篇求二进制的1的个数的博客,里面用按位与1的方式来判断位数是否为一。 如代码所示: #include <stdio.h> int num(int n) {int a 0;int i 0;while (i < 32){a a (n & 1);n n >> 1;i;}return a; } int main…...

解决Win10电脑无线网卡的移动热点无法开启问题
一、目的 利用无线网卡连接网络,然后又用无线网卡通过移动热点分享该网络。 移动热点,简单地说,就是将台式机或笔记本的 Internet 连接转化成 WIFI 信号以供移动设备无线上网的功能,硬件前提是电脑须安装有无线网卡。 二、问题 …...

Spring framework Day10:JSR330注入注解
前言 JSR330是Java社区标准化进程(Java Community Process,简称JCP)中的一个规范,全名为"Dependency Injection for Java",即Java的依赖注入规范。它定义了一组注解和相关的规范,用于实现依赖注…...

Java开发中List数据量大,需要分片批次处理
在开发过程中可能会遇到需要处理的List数据量过大,可以选择分批处理的方式对大量数据进行处理。 1、使用 apache 的工具包 <dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><v…...

Apache Doris 2.0.2 版本正式发布!
峰会官网已上线,最新议程请关注:doris-summit.org.cn 点击报名 亲爱的社区小伙伴们,Apache Doris 2.0.2 版本已于 2023 年 10 月 6 日正式发布,该版本对多个功能进行了更新优化,旨在更好地满足用户的需求。有 92 位贡献…...

transformers架构实现
目录 架构代码如下 模型打印如下 架构代码如下 import numpy as np from torch.autograd import Variable import copy from torch import softmax import math import torch import torch.nn.functional as F import torch.nn as nn # 构建Embedding类来实现文本嵌入层 class…...

C++类型推导
这里对C的类型推导方式进行一次全面的总结。 C中有三种类型推导的方式,分别是模板、auto以及decltype()。以下分别介绍这三种方式的同异。 一 模板 假设有这样的函数模板和这样的调用: template<typename T> void f(ParamType param);f(expr);…...

Open3D(C++) SVD分解求两个点云的变换矩阵
目录 一、算法原理二、代码实现三、结果展示四、相关链接一、算法原理 计算两个点云的质心计算中心化向量计算协方差矩阵奇异值分解,求解旋转矩阵 R R R计算平移向量 t t...

rtmp htttp推流Windows桌面到srs进行播放
推流命令: ffmpeg -f gdigrab -framerate 30 -i desktop -c:v libx264 -preset ultrafast -tune zerolatency -pix_fmt yuv420p -f flv rtmp://xxx.xxx.xxxx.xx/live/livestream 后面是推流地址 推流后的播放地址为: http://xxxxxx:8080/live/livestream.flv 可以写一个…...

NSSCTF做题(9)
[GDOUCTF 2023]<ez_ze> 看见输入框而且有提示说是ssti注入 输入{{7*7}} 试试,发现报错 输入{%%}发现了是jinja2模板 找到关键函数 Python SSTI利用jinja过滤器进行Bypass ph0ebuss Blog 原理见这篇文章,这里直接给出payload {%set ninedict(aaa…...

【09】基础知识:React组件的生命周期
组件从创建到死亡它会经历一些特定的阶段。 React 组件中包含一系列勾子函数(生命周期回调函数 <> 生命周期钩子函数 <> 生命周期函数 <> 生命周期钩子),会在特定的时刻调用。 我们在定义组件时,会在特定的生…...

Pytorch之ConvNeXt图像分类
文章目录 前言一、ConvNeXt设计决策1.设计方案2.Training Techniques3.Macro Design🥇Changing stage compute ratio🥈Change stem to "Patchify" 4.ResNeXt-ify5. Inverted Bottleneck6.Large Kernel Size7.Micro Design✨Replacing ReLU wit…...

Linux系统编程:makefile以及文件系统编程
增量编译概念 首先回顾一下我们之前写的各种gcc指令用来执行程序: 可以看见非常繁琐,两个文件就要写这么多,那要是成百上千岂不完蛋。 所以为了简化工作量,很自然的想到了将这些命令放在一起使用脚本文件来一键执行,…...

《动手学深度学习 Pytorch版》 8.5 循环神经网络的从零开始实现
%matplotlib inline import math import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2lbatch_size, num_steps 32, 35 train_iter, vocab d2l.load_data_time_machine(batch_size, num_steps) # 仍然使用时间机器数据集8.…...

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换
我们这里是利用按位与来计算的 我们可以想想怎么保留偶数上的位?我们可以利用0x55555555按位与上这个数就保留了偶数 我们知道,16进制0x55555555转换为二进制就是0x01010101010101010101010101010101 我们知道,二进制每一位,如…...

Zabbix监控系统详解2:基于Proxy分布式实现Web应用监控及Zabbix 高可用集群的搭建
文章目录 1. zabbix-proxy的分布式监控的概述1.1 分布式监控的主要作用1.2 监控数据流向1.3 构成组件1.3.1 zabbix-server1.3.2 Database1.3.3 zabbix-proxy1.3.4 zabbix-agent1.3.5 web 界面 2. 部署zabbix代理服务器2.1 前置准备2.2 配置 zabbix 的下载源,安装 za…...

docker 安装oracle
拉取镜像 拉取oracle_11g镜像 拉取oracle镜像(oracle 11.0.2 64bit 企业版 实例名: helowin) Oracle主要在Docker基础上安装,安装环境注意空间和内存,Oracle是一个非常庞大的一个软件, 建议使用网易镜像或阿里镜像网站这里以oracle 11.0.2…...

C++ vector 自定义排序规则(vector<vector<int>>、vector<pair<int,int>>)
vector< int > vector<int> vec{1,2,3,4};//默认从小到大排序 1234 sort(vec.begin(),vec.end()); //从大到小排序 4321 sort(vec.begin(),vec.end(),greater<int>());二维向量vector<vector< int >> vector<vector<int>> vec{{0…...

机器学习 Q-Learning
对马尔可夫奖励的理解 看的这个教程 公式:V(s) R(s) γ * V(s’) V(s) 代表当前状态 s 的价值。 R(s) 代表从状态 s 到下一个状态 s’ 执行某个动作后所获得的即时奖励。 γ 是折扣因子,它表示未来奖励的重要性,通常取值在 0 到 1 之间。…...

产品设计心得体会 优漫动游
产品设计需要综合考虑用户需求、市场需求和技术可行性,从而设计出能够满足用户需求并具有市场竞争力的产品。以下是我在产品设计方面的心得体会: 产品设计心得体会 1.深入了解用户需求:在产品设计之前,需要进行充分的用户调研…...

前端--CSS
文章目录 CSS的介绍 引入方式 代码风格 选择器 复合选择器 (选学) 常用元素属性 背景属性 圆角矩形 Chrome 调试工具 -- 查看 CSS 属性 元素的显示模式 盒模型 弹性布局 一、CSS的介绍 层叠样式表 (Cascading Style Sheets). CSS 能够对网页中元素位置的排版进行像素级精…...

实操指南|如何用 OpenTiny Vue 组件库从 Vue 2 升级到 Vue 3
前言 根据 Vue 官网文档的说明,Vue2 的终止支持时间是 2023 年 12 月 31 日,这意味着从明年开始: Vue2 将不再更新和升级新版本,不再增加新特性,不再修复缺陷 虽然 Vue3 正式版本已经发布快3年了,但据我了…...

系统架构设计:15 论软件架构的生命周期
目录 一 软件架构的生命周期 1 需求分析阶段 2 设计阶段 3 实现阶段 4 构件组装阶段...

金山wps golang面试题总结
简单自我介绍如果多个协程并发写map 会导致什么问题如何解决(sync.map,互斥锁,信号量)chan 什么时候会发生阻塞如果 chan 缓冲区满了是阻塞还是丢弃还是panicchan 什么时候会 panic描述一下 goroutine 的调度机制goroutine 什么时…...

计算机视觉实战--直方图均衡化和自适应直方图均衡化
计算机视觉 文章目录 计算机视觉前言一、直方图均衡化1.得到灰度图2. 直方图统计3. 绘制直方图4. 直方图均衡化 二、自适应直方图均衡化1.自适应直方图均衡化(AHE)2.限制对比度自适应直方图均衡化(CRHE)3.读取图片4.自适应直方图均…...