当前位置: 首页 > news >正文

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个像素。

在这里插入图片描述

图 1

在这里插入图片描述

图 2

(3)示例代码中 cv::Mat mask = (labels == i); 分析:当 i=1 时,labels图中只会把标号“1”的连通域提取出来,其他连通域都置为0,所以通过循环可依次找出不同标号的连通域。下面图3为标号“1”的连通域,可以看到其他白色区域都没有了。然后再对它进行查找轮廓,再添加矩形框,结果如图4。
在这里插入图片描述

图 3

在这里插入图片描述

图 4

下面图5为循环到标号“7”的连通域,详细像素值如图6,矩形框结果如图7

在这里插入图片描述

图 5

在这里插入图片描述

图 6

在这里插入图片描述

图 7

(4)示例代码的最终结果如图8。而原本只想要检测出三个水果,可以通过判定连通域大小,将较大的连通域删除,只保留较大的。示例代码修改如下,结果如图9所示

在这里插入图片描述

图 8
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;
}

在这里插入图片描述

图 9

二、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函数 前言 图像连通域&#xff0c;其实就是图像分割的一种方法。它通过检测像素之间的连接关系和相似性来划分图像中的区域&#xff0c;以便进行后续处理。图像邻域和图像邻域分析就不介绍了&#x…...

Rule-Engine-Starter V1.0.0

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

绘制X-Bar-S和X-Bar-R图,监测过程,计算CPK过程能力指数

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

【每日一句】只出现一次的数

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

GDB调试程序常用命令

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

C语言,求两个数的二进制表达中,有多少个位数不同

以前我的博客中写过一篇求二进制的1的个数的博客&#xff0c;里面用按位与1的方式来判断位数是否为一。 如代码所示&#xff1a; #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电脑无线网卡的移动热点无法开启问题

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

Spring framework Day10:JSR330注入注解

前言 JSR330是Java社区标准化进程&#xff08;Java Community Process&#xff0c;简称JCP&#xff09;中的一个规范&#xff0c;全名为"Dependency Injection for Java"&#xff0c;即Java的依赖注入规范。它定义了一组注解和相关的规范&#xff0c;用于实现依赖注…...

Java开发中List数据量大,需要分片批次处理

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

Apache Doris 2.0.2 版本正式发布!

峰会官网已上线&#xff0c;最新议程请关注&#xff1a;doris-summit.org.cn 点击报名 亲爱的社区小伙伴们&#xff0c;Apache Doris 2.0.2 版本已于 2023 年 10 月 6 日正式发布&#xff0c;该版本对多个功能进行了更新优化&#xff0c;旨在更好地满足用户的需求。有 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中有三种类型推导的方式&#xff0c;分别是模板、auto以及decltype()。以下分别介绍这三种方式的同异。 一 模板 假设有这样的函数模板和这样的调用&#xff1a; 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}} 试试&#xff0c;发现报错 输入{%%}发现了是jinja2模板 找到关键函数 Python SSTI利用jinja过滤器进行Bypass ph0ebuss Blog 原理见这篇文章&#xff0c;这里直接给出payload {%set ninedict(aaa…...

【09】基础知识:React组件的生命周期

组件从创建到死亡它会经历一些特定的阶段。 React 组件中包含一系列勾子函数&#xff08;生命周期回调函数 <> 生命周期钩子函数 <> 生命周期函数 <> 生命周期钩子&#xff09;&#xff0c;会在特定的时刻调用。 我们在定义组件时&#xff0c;会在特定的生…...

Pytorch之ConvNeXt图像分类

文章目录 前言一、ConvNeXt设计决策1.设计方案2.Training Techniques3.Macro Design&#x1f947;Changing stage compute ratio&#x1f948;Change stem to "Patchify" 4.ResNeXt-ify5. Inverted Bottleneck6.Large Kernel Size7.Micro Design✨Replacing ReLU wit…...

Linux系统编程:makefile以及文件系统编程

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

《动手学深度学习 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.…...

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换

我们这里是利用按位与来计算的 我们可以想想怎么保留偶数上的位&#xff1f;我们可以利用0x55555555按位与上这个数就保留了偶数 我们知道&#xff0c;16进制0x55555555转换为二进制就是0x01010101010101010101010101010101 我们知道&#xff0c;二进制每一位&#xff0c;如…...

Honey Select 2终极增强补丁:3分钟快速配置完整模组生态

Honey Select 2终极增强补丁&#xff1a;3分钟快速配置完整模组生态 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否曾为《Honey Select 2》的模组安装繁…...

OpenClaw语音控制之多麦克风阵列与声源定位技术的应用

7.1 麦克风阵列基础 7.1.1 阵列定义与原理 麦克风阵列是由多个麦克风按照特定几何结构排列组成的声学传感器系统。与单麦克风相比,阵列系统通过空间采样能够实现声场的时空联合处理,从而获得方向性选择能力。这种空间处理能力是语音交互系统在复杂声学环境中保持高性能的关…...

Python与OpenCV实战:图像对比度与亮度调整的算法解析与优化

1. 图像处理中的对比度与亮度基础 当你用手机拍完照片觉得太暗或者颜色不够鲜艳时&#xff0c;通常会下意识地滑动"亮度"和"对比度"调节条。这背后的数学原理&#xff0c;其实就是我们要探讨的核心算法。在OpenCV中&#xff0c;调整图像对比度和亮度的基础…...

Win11更新后Wifi图标消失?别急着重装系统,先试试这个官方驱动修复法

Win11更新后Wifi图标消失&#xff1f;三步精准定位官方驱动修复方案 刚更新完Windows 11系统&#xff0c;正准备继续手头的工作&#xff0c;突然发现任务栏右下角的Wifi图标不翼而飞。尝试重启电脑、重置网络设置&#xff0c;甚至检查了各种服务状态&#xff0c;问题依旧存在。…...

手把手搭建基于Kintex UltraScale+的Cameralink图像处理系统:从LVDS解码到GTY输出HDMI的完整Vivado工程解析

手把手搭建基于Kintex UltraScale的Cameralink图像处理系统&#xff1a;从LVDS解码到GTY输出HDMI的完整Vivado工程解析 在工业视觉和医疗影像领域&#xff0c;Cameralink接口凭借其高带宽和低延迟特性&#xff0c;依然是许多高端相机的首选接口方案。而Xilinx的Kintex UltraSca…...

【Typst源文件】Typst 纸张定义完全指南

Typst 通过 page 函数来定义纸张的尺寸、边距、方向等属性。通常使用 #set page() 规则在文档开头进行全局设置。 1. 基础纸张设置 1.1 使用标准纸张尺寸 Typst 支持丰富的标准纸张尺寸&#xff0c;只需传入纸张名称字符串即可&#xff1a; // 设置为 A4 纸张&#xff08;默…...

3步打造Windows桌面美学:TranslucentTB让任务栏焕发新生

3步打造Windows桌面美学&#xff1a;TranslucentTB让任务栏焕发新生 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB 一、为什么你的任务栏…...

从‘够用’到‘好用’:聊聊Artix-7 FPGA在工业视频处理中的那些‘甜点’级设计

从‘够用’到‘好用’&#xff1a;Artix-7 FPGA在工业视频处理中的设计哲学 工业视频处理领域正经历一场静默的革命——当4K/8K超高清、120fps高帧率成为行业热词时&#xff0c;真正推动生产线变革的却是那些在成本与性能间找到完美平衡点的解决方案。Artix-7系列FPGA&#xf…...

ai辅助开发c语言:如何利用快马智能编程助手精通数据结构与算法

今天想和大家分享一个特别实用的学习经验——如何用AI辅助工具高效学习C语言的数据结构与算法。作为一个刚接触数据结构的小白&#xff0c;我在实现单链表时遇到了不少坑&#xff0c;但通过InsCode(快马)平台的AI编程助手&#xff0c;整个过程变得轻松多了。 链表创建与节点插入…...

AI赋能编辑器:借助快马为Notepad++理念添加智能编程助手

今天想和大家分享一个有趣的实践&#xff1a;如何为传统代码编辑器&#xff08;比如Notepad&#xff09;注入AI能力。虽然Notepad本身轻量高效&#xff0c;但缺乏现代智能辅助功能。通过结合InsCode(快马)平台的AI能力&#xff0c;我们可以轻松实现智能补全、错误检查和代码优化…...