OpenCV C++实现区域面积筛选以及统计区域个数

目录

1、背景介绍

2、代码实现

2.1 获取原图

2.1.1 区域图像imread 

2.1.2 具体实现

2.2 获取图像大小 

2.3 阈值分割

2.3.1 阈值分割threshold

2.3.2 具体实现 

2.4  区域面积筛选

2.4.1 获取轮廓findContours

2.4.2 获取轮廓面积contourArea 

2.4.3 填充区域fillPoly

2.4.4 具体实现

2.5 统计区域个数并获取质心坐标

2.5.1  获取图像中心矩moments

2.5.2 具体实现

3、测试界面

4、总结 


1、背景介绍

本文实现了根据源图像的灰度值来分割成二值图像,通过面积筛选剔除掉面积小的区域,并统计区域的个数以及区域中心坐标。

IDE:Qt Creator 4.8.0  

编译器:MSVC 2017 64bit

Opencv库:opencv4.5.1

2、代码实现

2.1 获取原图

2.1.1 区域图像imread 

cv::Mat cv::imread(const String& filename, int flags = IMREAD_COLOR);
  • 第一个参数为图像地址
  • 第二个参数为读取类型
IMREAD_COLOR总是读取三通道图像
IMREAD_GRAYSCALE总是读取单通道图像 
IMREAD_ANYCOLOR通道数由文件实际通道数(不超过3)
IMREAD_ANYDEPTH允许加载超过8bit深度。
IMREAD_UNCHANGED等于将Cv::IMREAD_ANYCOLOR和CV::IMREAD_ANYDEPTH组合了起来。

2.1.2 具体实现

通过imread函数获取源图像,因为后续需要做阈值分割,需要用到灰度图像,所以imread的第二个参数取IMREAD_GRAYSCALE;

//获取图像
std::string strPicName = "./pic.png";
m_mSrcImage = cv::imread(strPicName, cv::IMREAD_GRAYSCALE);
cv::imshow("Src",m_mSrcImage);

2.2 获取图像大小 

//获取图像大小
int iHeight = m_mSrcImage.rows;
int iWidth = m_mSrcImage.cols;

2.3 阈值分割

2.3.1 阈值分割threshold

double cv::threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type);

src:输入的灰度图像或彩色图像。

dst:输出的二值化图像。

thresh:阈值,用于将像素点的亮度值与该值进行比较,从而确定像素点的颜色。

maxval:最大值,当像素点的亮度值大于等于阈值时,将其设置为该值。

type:二值化类型,常用的有以下几种:

THRESH_BINARY大于等于阈值的像素点设置为最大值,小于阈值的像素点设置为0。
THRESH_BINARY_INV大于等于阈值的像素点设置为0,小于阈值的像素点设置为最大值。
THRESH_TRUNC大于等于阈值的像素点设置为阈值,小于阈值的像素点保持不变。
THRESH_TOZERO大于等于阈值的像素点保持不变,小于阈值的像素点设置为0。
THRESH_TOZERO_INV大于等于阈值的像素点设置为0,小于阈值的像素点保持不变。

如果想要实现获取某个灰度阈值区间的区域,则可以先使用THRESH_TOZERO,获取小于thresholdMax的区域,然后使用THRESH_BINARY,获取大于thresholdMin的区域。

2.3.2 具体实现 

//阈值分割
double thresholdMin = 5;
double thresholdMax = 200;
double MaxVal = 255;
cv::Mat MatThreshold1;
cv::threshold(m_mSrcImage,MatThreshold1,thresholdMax,MaxVal,cv::THRESH_TOZERO_INV);
cv::Mat MatThreshold2;
cv::threshold(MatThreshold1,MatThreshold2,thresholdMin,MaxVal,cv::THRESH_BINARY);
cv::imshow("Threshold",MatThreshold2);

2.4  区域面积筛选

2.4.1 获取轮廓findContours

cv::void findContours(cv::InputOutputArray image,cv::OutputArrayOfArray contours,cv::OutputArray hierarchy,int mode,     int method,cv::Point offset = cv::Point())

findContours输入一个图像矩阵,返回一个双重向量  vector<vector<Point>> contours  每一组Point都连续,构成一组向量集合,在图像上的显示即为一个轮廓(点集),由于一张图像往往包含很多对象,因此一个轮廓不足以描述图像中的所有对象,因此还需要一个容器去包含所有的轮廓,我们称这个包含所有轮廓的容器为轮廓集。所以我们有上述的双重向量的定义方式。    轮廓数量=contours的元素个数

这里参数介绍太多了,就不具体介绍了。

2.4.2 获取轮廓面积contourArea 

double cv::contourArea( InputArray _contour, bool oriented )
  • contour:轮廓的像素点
  • oriented:区域面积是否具有方向的标志,true表示面积具有方向性,false表示不具有方向性,默认值为不具有方向性的false。

2.4.3 填充区域fillPoly

void cv::fillPoly(     InputOutputArray  img,InputArrayOfArrays       pts,const Scalar &        color,int   lineType = LINE_8,int   shift = 0,Point       offset = Point()
)

2.4.4 具体实现

  1. 通过findContours函数获取轮廓数据;
  2. 获取每个轮廓数据的面积,筛选给定的面积区间并保存到新的轮廓数据;
  3. 通过轮廓数据进行填充生成新的图像。
//区域面积筛选
double dAreaMin = 7000;
double dAreaMax = 9500;
std::vector<std::vector<cv::Point >> Contours;
cv::findContours(MatThreshold2,Contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE);
std::vector<std::vector<cv::Point >> SelectContours;
for(int i=0;i!=(int)Contours.size();i++)
{std::vector<cv::Point > Contour = Contours[i];double dArea = cv::contourArea(Contour,false);if(dArea>dAreaMin&&dArea<dAreaMax){SelectContours.push_back(Contour);}
}
cv::Mat SelectMat = cv::Mat::zeros(iHeight,iWidth,CV_8UC1);
cv::fillPoly(SelectMat,SelectContours,cv::Scalar(255,0,0));
cv::imshow("SelectMat",SelectMat);

2.5 统计区域个数并获取质心坐标

2.5.1  获取图像中心矩moments

cv::Moments cv::moments ( InputArray array,bool binaryImage = false)
  • opencv中提供了moments()来计算图像中的中心矩(最高到三阶);
  • x坐标通过cv::Moments的成员变量m10/m00获得;
  • y坐标通过cv::Moments的成员变量m01/m00获得;

2.5.2 具体实现

  1. 获取新生成区域的轮廓,根据双重向量的size获取区域个数
  2. 通过moments()来获取质心坐标
//获取各个区域质心的坐标vector
std::vector<std::vector<cv::Point >> CenterContours;
cv::findContours(SelectMat,CenterContours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE);
//统计区域个数
int iCount = CenterContours.size();
ui->sb_Count->setValue(iCount);
//获取质心坐标
std::vector<int> vCenterX;//质心X坐标
std::vector<int> vCenterY;//质心Y坐标
for(int i=0;i!=(int)CenterContours.size();i++)
{std::vector<cv::Point > CenterContour = CenterContours[i];cv::Moments M = cv::moments(CenterContour,false);int iCenterX = (M.m10/M.m00);int iCenterY = (M.m01/M.m00);vCenterX.push_back(iCenterX);vCenterY.push_back(iCenterY);
}

3、测试界面

4、总结 

本文通过opencv的函数进行图像的基本处理,实现了图像阈值化、面积筛选、统计区域个数、统计区域质心等功能模块,成功实现了功能需求。 

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

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

相关文章

http请求与响应

目录 HTTP请求格式 HTTP响应格式 HTTP请求格式 请求行&#xff1a;请求数据第一行(请求方式&#xff0c;资源路径&#xff0c;协议) 请求头&#xff1a;第二行开始&#xff0c;格式key:value 请求体&#xff1a;POST请求&#xff0c;存放在请求参数 非restful方式&#xff1…

浅谈大数据时代下的电商风控||电商数据API接口

抢抢抢&#xff01;最后1天&#xff0c;双十一直播活动来啦&#xff01;抢直播专属优惠…… 视频号 随着大数据时代的兴起&#xff0c;互联网电商风控已经从无风控、人工抽取规则为主的简易规则模型发展到当前基于大数据的风控。与金融风控不同&#xff0c;互联网电商风控呈现出…

详解MyBatis配置文件开发与注解式开发

首先呢&#xff0c;五一快来啦&#xff01;提前祝各位宝子们五一玩得开心&#xff0c;然后讲解一下MyBatis框架呀!!! 一.框架介绍 MyBatis 的主要特点 二.MyBatis工作流程 1. 初始化和配置 2. 创建 SqlSessionFactory 3. 获取 SqlSession 4. 映射器绑定 5. 执行操作 6.…

力扣1518. 换水问题

题目链接 力扣1518. 换水问题 简单方法(模拟) 思路 对换水进行模拟&#xff0c;每次喝完 n u m E x c h a n g e numExchange numExchange 瓶水后就去换一瓶水&#xff0c;直到不能再兑换为止&#xff0c;也就是剩余水的数量小于 n u m E x c h a n g e numExchange numE…

vscode中jsconfig.json文件首行提示错误

在使用react框架开发前端时&#xff0c;文件jsconfig.json首行提示错误&#xff0c;打开设置&#xff0c;勾选如下图这项

jupyter lab 如何安装和启动

Jupyter Lab 是一种基于 web 的交互式开发环境&#xff0c;用于 Jupyter 笔记本。与传统的 Jupyter 笔记本相比&#xff0c;它提供了更友好、更可扩展的界面&#xff0c;具有代码单元格、markdown 单元格、小部件和文件浏览器等功能。 1.安装 Jupyter Lab: 打开终端或命令提示…

【Go】通道作为函数参数

目录 一、Pings Pongs例子程序 二、使用通道进行任务分配和结果收集 三、使用通道进行错误处理 四、使用通道实现速率限制 五、使用通道进行数据同步 总结 共性 解决的问题类型 实际应用示例 Go 语言中&#xff0c;通道&#xff08;channel&#xff09;是实现协程&…

Linux 第十一章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

Java 图形化框架 - AWT、Swing

文章目录 关于 AWTAWT继承体系 关于 Swing关于 JFC 和 Swing Swing 组件组件层次Swing组件和AWT组件的对应关系&#xff1a;Swing组件按照功能来分类&#xff1a; Java使用AWT和Swing相关的类可以完成图形化界面编程&#xff0c;其中AWT的全称是抽象窗口工具集(Abstract Window…

北大发现了一种特殊类型的注意力头!

检索头的发现或许将有力地帮助大模型领域在提高长上下文推理能力、减少幻觉和压缩KV缓存方面的研究。 从 Claude100K 到 Gemini10M&#xff0c;我们正处于长上下文语言模型的时代。如何在长上下文中利用任何输入位置的信息&#xff1f;北大联合另外四所高校发现了一种特殊类型…

(四)后台-对文章的增删改查操作

&#xff08;四&#xff09;后台-对文章的增删改查操作 文章目录 &#xff08;四&#xff09;后台-对文章的增删改查操作一、RESTFUL API二、路由处理1、/home 后台首页页面2、/upload 文件上传功能 三、文章模块1、/list 获取文章列表 GetList2、/ 新增|编辑文章 SaveOrUpdate…

AI 提示词生成器

https://prompt-generator.ilovecoke.cc/参考 AI 提示词生成器

docker部署前端项目(三)简易迅速版本

前两个docker 部署都出现了 意外&#xff0c;通过dockerfile 文件操作的时候&#xff0c; 不是 npm 无法下载&#xff0c;就是 npm build 无法打包 总是困难重重&#xff0c;原因甚多&#xff0c;不是网络导致&#xff0c;就是版本不对&#xff0c; 原因可能是 node 版本和 npm…

运维 kubernetes(k8s)基础学习

一、容器相关 1、发展历程&#xff1a;主机–虚拟机–容器 主机类似别墅的概念&#xff0c;一个地基上盖的房子只属于一个人家&#xff0c;很多房子会空出来&#xff0c;资源比较空闲浪费。 虚拟机类似楼房&#xff0c;一个地基上盖的楼房住着很多人家&#xff0c;相对主机模式…

微信小程序的开发

1.了解项目的基本组成结构 pages 用来存放所有小程序的页面 utils 用来存放工具性质的模块(例如:格式化时间的自定义模块) app.js 小程序项目的入口文件 app.json 小程序项目的全局配置文件 app.wxss 小程序项目的全局样式文件 project.config.json 项目的配置文件 sitem…

Docker基础学习(5.Docker镜像命令)

⭐ 作者简介&#xff1a;码上言 ⭐ 代表教程&#xff1a;Spring Boot vue-element 开发个人博客项目实战教程 ⭐专栏内容&#xff1a;个人博客系统 ⭐我的文档网站&#xff1a;http://xyhwh-nav.cn/ ⭐微信公众号&#xff1a;码上言 文章目录 Docker run流程镜像是什么&a…

通用视觉多模态大模型 一统理解/生成/分割/编辑

这是一款通用视觉多模态大模型&#xff0c;支持从视觉理解到视觉生成、从低层次到高层次的一系列视觉任务&#xff0c;解决了困扰大语言模型产业已久的图像/视频模型割裂问题&#xff0c;提供了一个全面统一静态图像与动态视频内容的理解、生成、分割、编辑等任务的像素级通用视…

C++必修:类与对象(一)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C学习 贝蒂的主页&#xff1a;Betty’s blog 1. 面向过程与面向对象 1.1. 面向过程 我们之前学习的C语言就是一种面向过程的语…

【网络通信】初探网络层次结构(OSI七层网络模型)

随着信息技术的飞速发展&#xff0c;网络通信已经成为现代社会不可或缺的一部分。网络通信的实现离不开网络协议栈的支持&#xff0c;而网络协议栈则是由多个层次组成的。这些层次各自承担着不同的任务&#xff0c;共同构成了网络通信的基石。本文将对网络通信中的各类层进行详…

00.Jenkins 基本介绍与安装

Jenkins Jenkins 是一个开源的持续集成(Continuous Integration,CI)和持续交付(Continuous Delivery,CD)工具,用于自动化软件开发过程中的构建、测试和部署。它提供了丰富的插件生态系统,可以支持几乎所有主流的开发、构建和部署工具,使得软件开发团队能够更加高效地…