OpenCV4(C++)—— 图像连通域的详细分析

news2024/11/20 19:27:41

文章目录

  • 前言
  • 一、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) {
        // 提取当前连通域的mask
        cv::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) {
        // 提取当前连通域的mask
        cv::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的三通道类型了,但看起来还是跟灰度图一样。再放大看看数值,三个通道一样

在这里插入图片描述
因为原图是彩色图,示例代码中将其转为灰度图,我们也可以直接用原图来进行绘制,结果如下

在这里插入图片描述

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

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

相关文章

Redis第四五六章 持久化事务主从复制

Redis ⽀持 RDB 和 AOF 两种持久化机制&#xff0c;持久化功能有效地避免因进程退出造成数据丢失问题&#xff0c; 当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。 目录 第四章 持久化 4.1 RDB 4.1.1 触发机制 4.1.2 流程说明 4.1.3 RDB ⽂件的处理 4.1.4 RDB 的优…

Autoform R11 R10 R8共存绿色免安装版(解压即用)

使用说明&#xff1a; 如杀毒软件报毒&#xff0c;请关闭。 保证路径正确D:\Autoform 1.首次使用&#xff0c;请点击“首次运行使用.vbs” &#xff08;以后就不用点了&#xff09; 2.打开R8~R11快捷方式即可使用 3.如果提示证书报错&#xff0c; 就重启电脑后就可以了&#…

信必优收到全国性综合类证券客户表扬信

近日&#xff0c;信必优收到全国性综合类证券客户表扬信&#xff0c;客户高度表扬我司驻场员工认真负责的态度和专业扎实的技术能力&#xff0c;任务承担快&#xff0c;工作效率高&#xff0c;对项目顺利开展做出了积极贡献。 客户成立于1988年&#xff0c;在全国21个省级区域…

mars3d使用自己的字体库添加对应的图标

需要引入对应的文件 引入对应的图标文件 使用 效果

【算法-动态规划】两个字符串的删除操作-力扣 583

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

【超分】A Benchmark for Chinese-English Scene Text Image Super-resolution

中英文场景文本图像超分辨率的基准 摘要&#xff1a;场景文本图像超分&#xff08;STISR&#xff0c;Scene Text Image Super-resolution&#xff09;就是将低分辨率图像恢复为具有令人愉快的视觉和可读的文本内容。现有工作都是处理笔画简单的英文字符而不是复杂的中文字符。…

Axure RP医疗在线挂号问诊原型图医院APP原形模板

医疗在线挂号问诊Axure RP原型图医院APP原形模板&#xff0c;是一款原创的医疗类APP&#xff0c;设计尺寸采用iPhone13&#xff08;375*812px&#xff09;&#xff0c;原型图上加入了仿真手机壳&#xff0c;使得预览效果更加逼真。 本套原型图主要功能有医疗常识科普、医院挂号…

【JavaEE初阶】 volatile关键字 与 wait()方法和notify()方法详解

文章目录 &#x1f332;volatile 关键字&#x1f6a9;volatile能保证内存可见性&#x1f6a9;volatile 不保证原子性 &#x1f38b;wait 和 notify&#x1f6a9;wait()方法&#x1f6a9;notify()方法&#x1f6a9;notifyAll()方法&#x1f6a9;理解notify 和 notifyAll &#x…

商贸进销存软件怎么选?

本文将为大家讲解&#xff1a;1、商贸企业进销存流程上的难点&#xff1b;2、商贸企业如何选择进销存系统&#xff1f; 在当今快速发展的商业环境中&#xff0c;有效的进销存&#xff08;Inventory Management&#xff09;管理是商贸企业成功的关键因素之一。然而&#xff0c;…

linux环境下使用lighthouse与selenium

一、安装谷歌浏览器、谷歌浏览器驱动、lighthouse shell脚本 apt update && apt -y upgrade apt install -y curl curl -fsSL https://deb.nodesource.com/setup_18.x | bash apt install -y nodejs apt install -y npm npm install -g lighthouse apt-get install -y …

AutoRunner自动化测试工具

AutoRunner自动化测试工具(简称AR&#xff09;是泽众软件自主研发的自动化测试工具&#xff0c;也是一个自动测试框架&#xff0c;加载不同的测试组件&#xff0c;能够实现面向不同应用的测试。通过录制和编写测试脚本&#xff0c;实现功能测试、回归测试的自动化&#xff0c;自…

UE4中无法保存项目问题

系列文章目录 文章目录 系列文章目录前言一、解决方法 前言 取消&#xff1a;停止保存所有资产并返回编辑器。 重试&#xff1a;尝试再次保存资产。 继续&#xff1a;仅跳过保存该资产。 当我点击继续时&#xff0c;关闭项目&#xff0c;然后重新打开项目&#xff0c;发现之前…

代码随想录

前言 代码随想录算法训练营day04 (不会写数据结构的代码&#xff0c;对着力扣题解和代码随想录网站边敲学) 一、Leetcode24. 两两交换链表中的节点 1.题目 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值…

手部关键点检测1:手部关键点(手部姿势估计)数据集(含下载链接)

手部关键点检测1&#xff1a;手部关键点(手部姿势估计)数据集(含下载链接) 目录 手部关键点检测1&#xff1a;手部关键点(手部姿势估计)数据集(含下载链接) 1. 前言 2. 手部检测数据集&#xff1a; &#xff08;1&#xff09;Hand-voc1 &#xff08;2&#xff09;Hand-vo…

FMI标准:实现SkyEye与Simulink无需缝合的联合仿真

在汽车工业、航空、机电装备等领域存在着不同的应用、建模系统。在解决不同问题的过程中&#xff0c;为了仿真完整的系统&#xff0c;往往需要在不同的仿真程序之间进行交互&#xff0c;并且为了实现完整的调试&#xff0c;系统的集成必须确保来自不同供应商的仿真环境能够协同…

腾讯云 CODING 界面全新升级,代码仓库 Rebase 变基合并、批量复制事项等功能上线!

点击链接了解详情 金秋十月&#xff0c;腾讯云 CODING DevOps 焕新上线&#xff01;本次更新&#xff0c;我们不仅推出了全新的用户界面&#xff0c;还推出了一系列重磅产品能力&#xff0c;满足广大用户的日常研发与协作所需。 以下是 CODING 新功能速递&#xff0c;快来看看是…

文件的操作

前言&#xff1a;哈喽小伙伴们好久不见&#xff0c;国庆假期已经结束&#xff0c;接下来我们还是要马不停蹄的投入到学习当中&#xff0c;只有尽快调整状态回归学习&#xff0c;才能弯道超车。 今天我们一起来学习C语言——文件操作。 本篇文章讲到的所有函数均需要头文件#inc…

国内ITSM发展的趋势

多年来&#xff0c;随着客户业务需求、工作文化、技术创新的不断变化以及新的IT环境的出现&#xff0c; IT支持也出现了新的变化&#xff0c;由单一的IT帮助台&#xff08; IT help desk&#xff09;逐渐转变为了综合性的IT服务台&#xff08; IT service desk&#xff09;&…

基于intel D4系列深度相机 (D455)的单点测距和两点距离测量(代码讲解超详细)

目录 1.简介 1.1 intel D4系列深度相机 (D455) 1.2结构光(Structured-light) 2.基于深度相机的单点测距和两点距离测量 2.1函数详解 2.2 全部代码 1.简介 1.1 intel D4系列深度相机 (D455) Intel RealSense D435、D455等D4系列&#xff1a; Intel D4系列深度相机是由英特…

有人因它丢掉offer!背景调查到底有什么魔力?

求职时&#xff0c;公司往往会对应聘者过往经历做一些背景调查——也被叫做背调。 据i背调人才研究院数据显示&#xff0c;2022年的求职失信占比仍然较高&#xff0c;有39.13%的候选人存在职业信用异常。而随着近些年来&#xff0c;整体就业市场和职业发展中竞争压力不断加剧&…