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

opencv连通域标记 connectedComponentsWithStats()函数

1.背景
由于需要将图像中的目标提取出来,采用了先分割得到二值化图,然后再进行连通域统计找到最大的连通域,计算其外接矩形作为目标框的方法。
2.函数定义
通过搜索,发现在OpenCV 3中提供了连通域标记相关的两个很好的函数,分别是

cv::connectedComponents() 和cv::connectedComponentsWithStats(),在OpenCV 2中没有这两个函数。
2.1 connectedComponents()
仅仅创建了一个标记图(图中不同连通域使用不同的标记,和原图宽高一致);
调用格式为:

int cv::connectedComponents (
    cv::InputArrayn image, // input 8-bit single-channel (binary)
    cv::OutputArray labels, // output label map
    int connectivity = 8, // 4- or 8-connected components
    int ltype = CV_32S // Output label type (CV_32S or CV_16U)
);

2.2 connectedComponentsWithStats()
也可以完成上面任务,除此之外,还可以返回每个连通区域的重要信息-- bounding box, area, and center of mass( centroid)。函数返回值为连通区域的总数N,范围为[0,N-1],其中0代表背景
调用格式为:

int cv::connectedComponentsWithStats (
    cv::InputArrayn image, // input 8-bit single-channel (binary)
    cv::OutputArray labels, // output label map
    cv::OutputArray stats, // Nx5 matrix (CV_32S) of statistics:
    // [x0, y0, width0, height0, area0;
    // ... ; x(N-1), y(N-1), width(N-1),
    // height(N-1), area(N-1)]
    cv::OutputArray centroids, // Nx2 CV_64F matrix of centroids:
    // [ cx0, cy0; ... ; cx(N-1), cy(N-1)]
    int connectivity = 8, // 4- or 8-connected components
    int ltype = CV_32S // Output label type (CV_32S or CV_16U)
);

参数介绍如下:
左侧返回值
num_labels:所有连通域的数目,注:第0个代表背景
右侧输入参数
image:也就是输入图像,必须是二值图,即8位单通道图像。(因此输入图像必须先进行二值化处理才能被这个函数接受)
labels:图像上每一像素的标记,用数字1、2、3…表示(不同的数字表示不同的连通域)
stats:每一个标记的统计信息,是一个5列的矩阵,每一行对应每个连通区域的外接矩形的左上角坐标x、y,以及外接矩形的宽高width、height和面积area,
centroids:连通域的中心点
connectivity:可选值为4或8,也就是使用4连通还是8连通。
ltype:输出图像标记的类型,目前支持CV_32S 和 CV_16U。 返回值:

其中, stats包含了标签为i的连通域的一些信息,可以如下访问标签为i的连通域的面积

stats.at<int>(i, CC_STAT_AREA)

访问外接矩形的参数:

//矩形左上角x
x = stats.at<int>(max_idx, cv::CC_STAT_LEFT);
//矩形左上角y
y = stats.at<int>(max_idx, cv::CC_STAT_TOP);
//矩形高
h = stats.at<int>(max_idx, cv::CC_STAT_HEIGHT);
//矩形宽
w = stats.at<int>(max_idx, cv::CC_STAT_WIDTH);

3.过程
一开始再手机上查到这个函数,使用了索引0,结果直接把全图给框住了,后来仔细看了函数的定义,选择1,把除了背景以外的最大值给圈出来了。

Mat img = imread("F:\\C++_Project\\1.jpg",0);
Mat labels, stats, centroids,BW;
//对于OpenCV来说,白色代表有数据,黑色代表没有数据,所以图像输入之前要转换成”黑底白图“
threshold(img, BW, 11, 255, THRESH_BINARY);
int nccomps = connectedComponentsWithStats(BW, labels, stats, centroids);
int max_area=0, max_idx=0;
//找到最大的连通域区域和索引
for (int i = 1; i < stats.rows; i++)
{
	if (stats.at<int>(i, cv::CC_STAT_AREA)>max_area)
	{
		max_area = stats.at<int>(i, cv::CC_STAT_AREA);
		max_idx = i;
	}
}
//提取最大区域的外接矩形参数
int x0, y0, w, h, x1, y1;
x0 = stats.at<int>(max_idx, cv::CC_STAT_LEFT);
y0 = stats.at<int>(max_idx, cv::CC_STAT_TOP);
h = stats.at<int>(max_idx, cv::CC_STAT_HEIGHT);
w = stats.at<int>(max_idx, cv::CC_STAT_WIDTH);
//标记矩形
cv::Rect rect(x0, y0, w, h);
cv::rectangle(img, rect, cv::Scalar::all(int(255)), 1);
cv::imshow("BW img", img);
cv::waitKey(0);
return 0;

4.小结
一个小问题,但由于没有理清函数定义和用法,就直接用了,导致查bug花了不少时间。以后遇到一个新的函数时,应该先看定义,输入、输出的含义,再应用。
————————————————
参考:1.CSDN博主「i_chaoren」
2.CSDN博主「NCUTer」

相关文章:

  • 【C#在资源管理器中显示自定义文件格式的缩略图】
  • 【NLP】第2章 开始使用 Transformer 模型的架构
  • 电容的分类
  • MYBatis-Plus常用注解@TableName、@TableId、@TableField、@TableLogic
  • 沉睡者IT - 贡献者和律师的Web3指南:充分去中心化
  • unityEditor扩展开发onGUI添加右键菜单
  • 认识 fcntl 接口函数
  • a16z:呼吁SEC改革加密资产托管规则的建议
  • 通过虚拟代理服务器解决Axios跨域问题[Vue.js项目实践: 新冠自检系统]
  • 【JavaScript-动画原理】如何使用js进行动画效果的实现
  • Servlet对象的生命周期
  • python入门基础-数据类型有序序列和无序序列;
  • MySQL 高级SQL语句 (二)
  • 小米面试——计算机视觉算法实习生
  • 基于JavaWeb的疫情期间社区出入管理系统设计与实现
  • Angular6错误 Service: No provider for Renderer2
  • CSS 专业技巧
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • JavaScript新鲜事·第5期
  • nodejs:开发并发布一个nodejs包
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • SOFAMosn配置模型
  • webgl (原生)基础入门指南【一】
  • yii2中session跨域名的问题
  • 前嗅ForeSpider中数据浏览界面介绍
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 如何设计一个比特币钱包服务
  • 数据可视化之 Sankey 桑基图的实现
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​力扣解法汇总946-验证栈序列
  • ​人工智能书单(数学基础篇)
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #{}和${}的区别是什么 -- java面试
  • #1015 : KMP算法
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (C#)一个最简单的链表类
  • (ibm)Java 语言的 XPath API
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (四)图像的%2线性拉伸
  • ****Linux下Mysql的安装和配置
  • *Django中的Ajax 纯js的书写样式1
  • .net 调用php,php 调用.net com组件 --
  • .NET6 命令行启动及发布单个Exe文件
  • .net反编译工具
  • .考试倒计时43天!来提分啦!
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [AIGC] 如何建立和优化你的工作流?
  • [C#]OpenCvSharp使用帧差法或者三帧差法检测移动物体
  • [C#]无法获取源 https://api.nuge t.org/v3-index存储签名信息解决方法
  • [java基础揉碎]关系运算符(比较运算符)逻辑运算符赋值运算符三元运算符运算符的优先级