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

news2025/1/13 7:36:10

目录

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.coloradmin.cn/o/1628985.html

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

相关文章

JEECG/SpringBoot集成flowable流程框架

IDEA安装Flowable BPMN visualizer插件 pom.xml中引入flowable相关依赖 <dependency><groupId>org.flowable</groupId><artifactId>flowable-spring-boot-starter</artifactId><version>6.7.2</version></dependency><depe…

kotlin 编写一个简单的天气预报app (七)使用material design

一、优化思路 对之前的天气预报的app进行了优化&#xff0c;原先的天气预报程序逻辑是这样的。 使用text和button组合了一个输入城市&#xff0c;并请求openweathermap对应数据&#xff0c;并显示的功能。 但是搜索城市的时候&#xff0c;可能会有错误&#xff0c;比如大小写…

SpringBoot项目启动,传参有哪些方式?

SpringBoot项目启动&#xff0c;传参有哪些方式&#xff1f; 1.Spring级别的参数 直接在启动 Spring Boot 应用的命令行中使用 -- 后跟参数名和值的方式来传递参数。 记住&#xff1a;一般是对于Spring Boot应用特有的配置参数&#xff0c;确保它们遵循Spring Boot的配置属性命…

Mediasoup-demo 本地启动步骤(超详细)

Mediasoup-demo 本地启动步骤&#xff08;超详细&#xff09; 一.本人环境 系统&#xff1a;macos13.6.3 node: v16.20.2 npm:8.19.4 python: 3.9.6 二.下载代码 git 下载代码&#xff1a; git clone gitgithub.com:versatica/mediasoup-demo.git 三.代码介绍 下载下来…

电磁仿真--基本操作-CST-(4)

目录 1. 简介 2. 建模过程 2.1 基本的仿真配置 2.2 构建两个圆环体和旋转轴 2.3 切分圆环体 2.4 衔接内外环 2.5 保留衔接部分 2.6 绘制内螺旋 2.7 绘制外螺旋 2.8 查看完整体 2.9 绘制引脚 2.10 设置端口 2.11 仿真结果 3. 使用Digilent AD2进行测试 3.1 进行…

十、多模态大语言模型(MLLM)

1 多模态大语言模型&#xff08;Multimodal Large Language Models&#xff09; 模态的定义 模态&#xff08;modal&#xff09;是事情经历和发生的方式&#xff0c;我们生活在一个由多种模态(Multimodal)信息构成的世界&#xff0c;包括视觉信息、听觉信息、文本信息、嗅觉信…

Java 提取HTML文件中的文本内容

从 HTML 文件中提取文本内容是数据抓取中的一个常见任务&#xff0c;你可以将提取的文本信息用于编制报告、进行数据分析或其他处理。本文分享如何使用免费 Java API 从HTML 文件中提取文本内容。 安装免费Java库&#xff1a; 要通过Java提取HTML文本&#xff0c;需要用到Free…

基于车载点云数据的城市道路特征目标提取与三维重构

作者&#xff1a;邓宇彤&#xff0c;李峰&#xff0c;周思齐等 来源&#xff1a;《北京工业大学学报》 编辑&#xff1a;东岸因为一点人工一点智能公众号 基于车载点云数据的城市道路特征目标提取与三维重构本研究旨在弥补现有研究在处理复杂环境和大数据量上的不足&#xf…

灯塔:MySQL笔记 (1)

数据库相关概念 名称全称简称数据库存储数据的仓库&#xff0c;数据有组织的进行存储DateBase(DB)数据库管理系统操控和管理数据据库的大型软件DateBase Management System (DBSM)SQL操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库——标准Structured Que…

python生成二维码及进度条源代码

一、进度条 1、利用time模块实现 import time for i in range(0, 101, 2):time.sleep(0.3)num i // 2if i 100:process "\r[%3s%% ]: |%-50s|\n" % (i, # * num)else:process "\r[%3s%% ]: |%-50s|" % (i, # * num)print(process, end, flushTrue)2、使…

CentOS/Anolis的Linux系统如何通过VNC登录远程桌面?

综述 需要在server端启动vncserver&#xff0c;推荐tigervnc的server 然后再本地点来启动client进行访问&#xff0c;访问方式是IPport&#xff08;本质是传递数据包到某个ip的某个port&#xff09; 然后需要防火墙开启端口 服务器上&#xff1a;安装和启动服务 安装服务 y…

vivado Aurora 8B/10B IP核(1)

Aurora 8B/10B IP 支持 Kintex -7, Virtex -7 FPGA GTP 和 GTH 收发器&#xff0c;Artix -7 FPGA GTP 收发器, Zynq -7000 GTP and GTP 收发器。Aurora 8B/10B IP core 可以工作于单工或者全双工模式。IP CODE的使用也非常简单&#xff0c;支持 AMBA总线的 AXI4-Stream 协议。…

2024蓝桥杯CTF--逆向

蓝桥杯付费CT--逆向 题目&#xff1a;RC4题目&#xff1a;happytime总结&#xff1a; 题目&#xff1a;RC4 先查壳&#xff0c;无壳&#xff0c;并且是32位&#xff1a; 用32位的ida打开&#xff0c;直接定位到main函数&#xff1a; 重点关注sub_401005函数&#xff0c;这个应…

编程学习系列(1):计算机发展及应用(1)

前言&#xff1a; 最近我在整理书籍时&#xff0c;发现了一些有关于编程的学习资料&#xff0c;我派蒙也不是个吝啬的人&#xff0c;从今天开始就陆续分享给大家。 计算机发展及应用&#xff08;1&#xff09; 1944 年美国数学家冯诺依曼&#xff08;现代计算机之父&#xff…

【Redis 开发】Redis持久化(RDB和AOF)

Redis持久化 RDBAOFRDB和AOF的区别 RDB RDB全称Redis DataBase Backup file &#xff08;Redis数据备份文件&#xff09;&#xff0c;也被称为Redis数据快照&#xff0c;简单来说就是把内存中的所有数据都记录到磁盘中&#xff0c;当Redis实例故障重启后&#xff0c;从磁盘读取…

GPU:使用gpu-burn压测GPU

简介&#xff1a;在测试GPU的性能问题时&#xff0c;通常需要考虑电力和散热问题。使用压力测试工具&#xff0c;可以测试GPU满载时的状态参数&#xff08;如温度等&#xff09;。gpu_burn是一个有效的压力测试工具。通过以下步骤可以进行测试。 官网&#xff1a; http://www…

Xline中区间树实现小结

Table of Contents 实现区间树的起因区间树实现简介 插入/删除查询重叠操作使用Safe Rust实现区间树 问题Rc<RefCell<T>> i. 线程安全问题其他智能指针 i. Arc<Mutex<T>>? ii. QCell数组模拟指针总结 01、实现区间树的起因 在Xline最近的一次重构中…

基于PI控制器的DC-DC结构PWM系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于PI控制器的DC-DC结构PWM系统simulink建模与仿真。包括IGBT结构&#xff0c;PI控制器结构&#xff0c;PWM模块等。 2.系统仿真结果 3.核心程序与模型 版本&#xff1a;MA…

【yolov8算法道路-墙面裂缝检测-汽车车身凹陷-抓痕-损伤检测】

yolo算法道路-墙面裂缝检测-汽车车身凹陷-抓痕-损伤检测 1. yolo算法裂缝检测-汽车车身凹陷-抓痕检测-汽车车身损伤检测2. yolo房屋墙面路面裂缝-发霉-油漆脱落-渗水-墙皮脱落检测3. 水泥墙面裂缝检测 YOLOv8算法是一种先进的目标检测技术&#xff0c;它基于YOLO系列算法的改进…

上位机图像处理和嵌入式模块部署(树莓派4b之wifi切换)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前期我们在烧录镜像的时候&#xff0c;一般会配置一个默认的、带wifi配置的镜像。这主要是为了通过局域网扫描&#xff0c;或者输入arp -a的方式&a…