[C++]使用OpenCV去除面积较小的连通域
这是后期补充的部分,和前期的代码不太一样
效果图

源代码
//测试
void CCutImageVS2013Dlg::OnBnClickedTestButton1()
{vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point> >::iterator itr; //轮廓迭代器vector<Point2d>::iterator itrc; //质心坐标迭代器vector<vector<Point> > con; //当前轮廓double area;double minarea = 1000;double maxarea = 0;Moments mom; // 轮廓矩Mat image, gray, edge, dst;image = imread("D:\\66.png");cvtColor(image, gray, COLOR_BGR2GRAY);Mat rgbImg(gray.size(), CV_8UC3); //创建三通道图blur(gray, edge, Size(3, 3)); //模糊去噪threshold(edge, edge, 200, 255, THRESH_BINARY_INV); //二值化处理,黑底白字//--------去除较小轮廓,并寻找最大轮廓--------------------------findContours(edge, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); //寻找轮廓itr = contours.begin(); //使用迭代器去除噪声轮廓while (itr != contours.end()){area = contourArea(*itr); //获得轮廓面积if (area<minarea) //删除较小面积的轮廓 {itr = contours.erase(itr); //itr一旦erase,需要重新赋值}else{itr++;}if (area>maxarea) //寻找最大轮廓{maxarea = area;}}dst = Mat::zeros(image.rows, image.cols, CV_8UC3);/*绘制连通区域轮廓,计算质心坐标*/Point2d center;itr = contours.begin();while (itr != contours.end()){area = contourArea(*itr); con.push_back(*itr); //获取当前轮廓if (area == maxarea){vector<Rect> boundRect(1); //定义外接矩形集合boundRect[0] = boundingRect(Mat(*itr));cvtColor(gray, rgbImg, COLOR_GRAY2BGR);Rect select;select.x = boundRect[0].x;select.y = boundRect[0].y;select.width = boundRect[0].width;select.height = boundRect[0].height;rectangle(rgbImg, select, Scalar(0, 255, 0), 3, 2); //用矩形画矩形窗drawContours(dst, con, -1, Scalar(0, 0, 255), 2); //最大面积红色绘制}elsedrawContours(dst, con, -1, Scalar(255, 0, 0), 2); //其它面积蓝色绘制con.pop_back();//计算质心mom = moments(*itr);center.x = (int)(mom.m10 / mom.m00);center.y = (int)(mom.m01 / mom.m00);centers.push_back(center);itr++;}imshow("rgbImg", rgbImg);//imshow("gray", gray);//imshow("edge", edge);imshow("origin", image);imshow("connected_region", dst);waitKey(0);return;
}
前期做的,方法可能不太一样
一,先看效果图
原图

处理前后图
二,实现源代码
//=======函数实现=====================================================================
void RemoveSmallRegion(Mat &Src, Mat &Dst, int AreaLimit, int CheckMode, int NeihborMode)
{int RemoveCount = 0;//新建一幅标签图像初始化为0像素点,为了记录每个像素点检验状态的标签,0代表未检查,1代表正在检查,2代表检查不合格(需要反转颜色),3代表检查合格或不需检查 //初始化的图像全部为0,未检查 Mat PointLabel = Mat::zeros(Src.size(), CV_8UC1);if (CheckMode == 1)//去除小连通区域的白色点 {//cout << "去除小连通域.";for (int i = 0; i < Src.rows; i++){for (int j = 0; j < Src.cols; j++){if (Src.at<uchar>(i, j) < 10){PointLabel.at<uchar>(i, j) = 3;//将背景黑色点标记为合格,像素为3 }}}}else//去除孔洞,黑色点像素 {//cout << "去除孔洞";for (int i = 0; i < Src.rows; i++){for (int j = 0; j < Src.cols; j++){if (Src.at<uchar>(i, j) > 10){PointLabel.at<uchar>(i, j) = 3;//如果原图是白色区域,标记为合格,像素为3 }}}}vector<Point2i>NeihborPos;//将邻域压进容器 NeihborPos.push_back(Point2i(-1, 0));NeihborPos.push_back(Point2i(1, 0));NeihborPos.push_back(Point2i(0, -1));NeihborPos.push_back(Point2i(0, 1));if (NeihborMode == 1){//cout << "Neighbor mode: 8邻域." << endl;NeihborPos.push_back(Point2i(-1, -1));NeihborPos.push_back(Point2i(-1, 1));NeihborPos.push_back(Point2i(1, -1));NeihborPos.push_back(Point2i(1, 1));}else int a = 0;//cout << "Neighbor mode: 4邻域." << endl;int NeihborCount = 4 + 4 * NeihborMode;int CurrX = 0, CurrY = 0;//开始检测 for (int i = 0; i < Src.rows; i++){for (int j = 0; j < Src.cols; j++){if (PointLabel.at<uchar>(i, j) == 0)//标签图像像素点为0,表示还未检查的不合格点 { //开始检查 vector<Point2i>GrowBuffer;//记录检查像素点的个数 GrowBuffer.push_back(Point2i(j, i));PointLabel.at<uchar>(i, j) = 1;//标记为正在检查 int CheckResult = 0;for (int z = 0; z < GrowBuffer.size(); z++){for (int q = 0; q < NeihborCount; q++){CurrX = GrowBuffer.at(z).x + NeihborPos.at(q).x;CurrY = GrowBuffer.at(z).y + NeihborPos.at(q).y;if (CurrX >= 0 && CurrX<Src.cols&&CurrY >= 0 && CurrY<Src.rows) //防止越界 {if (PointLabel.at<uchar>(CurrY, CurrX) == 0){GrowBuffer.push_back(Point2i(CurrX, CurrY)); //邻域点加入buffer PointLabel.at<uchar>(CurrY, CurrX) = 1; //更新邻域点的检查标签,避免重复检查 }}}}if (GrowBuffer.size()>AreaLimit) //判断结果(是否超出限定的大小),1为未超出,2为超出 CheckResult = 2;else{CheckResult = 1;RemoveCount++;//记录有多少区域被去除 }for (int z = 0; z < GrowBuffer.size(); z++){CurrX = GrowBuffer.at(z).x;CurrY = GrowBuffer.at(z).y;PointLabel.at<uchar>(CurrY, CurrX) += CheckResult;//标记不合格的像素点,像素值为2 }//********结束该点处的检查********** }}}CheckMode = 255 * (1 - CheckMode);//开始反转面积过小的区域 for (int i = 0; i < Src.rows; ++i){for (int j = 0; j < Src.cols; ++j){if (PointLabel.at<uchar>(i, j) == 2){Dst.at<uchar>(i, j) = CheckMode;}else if (PointLabel.at<uchar>(i, j) == 3){Dst.at<uchar>(i, j) = Src.at<uchar>(i, j);}}}//cout << RemoveCount << " objects removed." << endl;
}
//=======函数实现=====================================================================
//=======调用函数=====================================================================Mat img;img = imread("D:\\1_1.jpg", 0);//读取图片threshold(img, img, 128, 255, CV_THRESH_BINARY_INV);imshow("去除前", img);Mat img1;RemoveSmallRegion(img, img, 200, 0, 1);imshow("去除后", img);waitKey(0);
//=======调用函数=====================================================================
相关文章:
[C++]使用OpenCV去除面积较小的连通域
这是后期补充的部分,和前期的代码不太一样 效果图 源代码 //测试 void CCutImageVS2013Dlg::OnBnClickedTestButton1() {vector<vector<Point> > contours; //轮廓数组vector<Point2d> centers; //轮廓质心坐标 vector<vector<Point&…...
vscode连接不上,终端ssh正常,一直输入密码正确但是无法登录
若是之前链结果突然等不上,使用第一个链接 若是第一次链接连不上,先使用第二个链接,在使用第一个链接 原因:原因是服务器端的wget命令不能使用,vscode需要服务器端下载个文件,无法下载就导致了如上的错误…...
Hive on Spark 配置
目录 1 Hive 引擎简介2 Hive on Spark 配置2.1 在 Hive 所在节点部署 Spark2.2 在hive中创建spark配置文件2.3 向 HDFS上传Spark纯净版 jar 包2.4 修改hive-site.xml文件2.5 Hive on Spark测试2.6 报错 1 Hive 引擎简介 Hive引擎包括:MR(默认)…...
ROS 基本
ROS创建自己的功能包 ROS中工作空间(workspace)是一个存放工程开发相关文件的文件夹,其中有四个文件夹。 src:代码空间(Source Space)build:编译空间(Build Space)devel:开发空间(Development Space)install:安装空间(Install Space) OK接下来创作工作空间&#…...
Pygame基础9-射击
简介 玩家用鼠标控制飞机(白色方块)移动,按下鼠标后,玩家所在位置出现子弹,子弹匀速向右飞行。 代码 没有什么新的东西,使用两个精灵类表示玩家和子弹。 有一个细节需要注意,当子弹飞出屏幕…...
Ps:颜色查找
颜色查找 Color Lookup命令通过应用预设的 LUT 来改变图像的色彩和调性,从而为摄影师和设计师提供了一种快速实现复杂色彩调整的方法,广泛应用于颜色分级、视觉风格的统一和创意色彩效果的制作。 Ps菜单:图像/调整/颜色查找 Adjustments/Colo…...
vue3+vite 模板vue3-element-admin框架如何关闭当前页面跳转 tabs
使用模版: 有来开源组织 / vue3-element-admin 需要关闭的.vue 页面增加以下方法 //setup 里import {LocationQuery, useRoute, useRouter} from "vue-router"; const router useRouter(); function close() {console.log(|--router.currentRoute.value, router.cur…...
JavaScript 对象管家 Proxy
JavaScript 在 ES6 中,引入了一个新的对象类型 Proxy,它可以用来代理另一个对象,并可以在代理过程中拦截、覆盖和定制对象的操作。Proxy 对象封装另一个对象并充当中间人,其提供了一个捕捉器函数,可以在代理对象上拦截…...
Qt + Vs联合开发
Qt + Vs联合开发 文章目录 Qt + Vs联合开发环境说明VS+Qt安装注意事项QtCreator msvc编译器配置Visual Studio 2019 + Qt 5.12.10Visual Studio 2015 + Qt5.12.10VsQt环境配置安装插件 Qt Visual Studio Tools插件配置Qt创建项目Vs创建Qt项目VsQt工程转换Vs工程转Qt工程Qt工程转…...
开源知识库平台Raneto--使用Docker部署Raneto
文章目录 一、Raneto介绍1.1 Raneto简介1.2 知识库介绍 二、阿里云环境2.1 环境规划2.2 部署介绍 三、环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Raneto镜像五、部署Raneto知识库平台5.1 创建挂载目录5.2 编辑config.js文件5.3 编…...
鸿蒙原OS开发实例:【ArkTS类库单次I/O任务开发】
Promise和async/await提供异步并发能力,适用于单次I/O任务的场景开发,本文以使用异步进行单次文件写入为例来提供指导。 实现单次I/O任务逻辑。 import fs from ohos.file.fs; import common from ohos.app.ability.common;async function write(data:…...
C语言:二叉树的构建
目录 一、二叉树的存储 1.1 顺序存储 1.2 链式存储 二、二叉树的顺序结构及实现 2.1堆的概念及结构 2.2堆的构建 2.3堆的插入 2.4堆顶的删除 2.5堆的完整代码 三、二叉树的链式结构及实现 3.1链式二叉树的构建 3.2链式二叉树的遍历 3.2.1前序遍历 …...
软件测试工程师面试汇总功能测试篇
Q:一、进行测试用例设计的时候用到的方法有哪些? A:最常使用的测试用例设计方法包括等价类划分法、边界值分析方法、场景法、错误推测法。其中,最容易 发现错误的是边界值法,使用最多的是场景法。以注册为例:首先从需求确定用户名…...
javaAPI1
API application pragramming interface 应用程序编程接口 除java.lang包以外,其他包中的类在使用时需要导入 建包 package com.abc.javabean; 导包格式,import 包名.类名 API使用技巧 1,先看关键字 2,看参数列表 3,看返回值类型 String 封装字符串和处理字符串的类…...
案例研究|DataEase实现物业数据可视化管理与决策支持
河北隆泰物业服务有限责任公司(以下简称为“隆泰物业”)创建于2002年,总部设在河北省高碑店市,具有国家一级物业管理企业资质,通过了质量体系、环境管理体系、职业健康安全管理体系等认证。自2016年至今,隆…...
Android Studio Iguana | 2023.2.1 补丁 1
Android Studio Iguana | 2023.2.1 Canary 3 已修复的问题Android Gradle 插件 问题 295205663 将 AGP 从 8.0.2 更新到 8.1.0 后,任务“:app:mergeReleaseClasses”执行失败 问题 298008231 [Gradle 8.4][升级] 由于使用 kotlin gradle 插件中已废弃的功能&#…...
iOS17 隐私协议适配详解
1. 背景 网上搜了很多文章,总算有点头绪了。其实隐私清单最后做出来就是一个plist文件。找了几个常用三方已经配好的看了看,比着做就好了。 WWDC23 中关于隐私部分的更新(WWDC23 隐私更新官网),其中提到了第三方 SDK 的…...
LeetCode 每日一题 Day 116-122
2580. 统计将重叠区间合并成组的方案数 给你一个二维整数数组 ranges ,其中 ranges[i] [starti, endi] 表示 starti 到 endi 之间(包括二者)的所有整数都包含在第 i 个区间中。 你需要将 ranges 分成 两个 组(可以为空…...
linux离线安装jenkins及使用教程
本教程采用jenkins.war的方式离线安装部署,在线下载的方式会遇到诸多问题,不宜采用 基本环境: 1.jdk环境,Jenkins是java语言开发的,因需要jdk环境。 2.git/svn客户端,因一般代码是放在git/svn服务器上的&a…...
NXP-S32DS软件安装
文章目录 一、安装包获取二、S32DS安装三、芯片插件安装 一、安装包获取 登录NXP官网,进入软件目录https://www.nxp.com/ 下载S32DS软件和RTD驱动库,并安装S32DS软件。 单击“S32DS.3.5_b220726_win32.x86_64.exe”下载该软件 点击“License Keys”&…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
