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

计算机视觉全系列实战教程 (十二):图像分割(阈值分割threshold、分水岭算法watershed的使用步骤、洪水填充floodFill算法的使用)

1.图像分割概述

(1)What(什么是图像分割)

将图像划分为不同的子区域,使得同一子区域具有较高的相似性,不同的子区域具有明显的差异性

(2)Why(对图像进行分割有什么作用)

  • 医学领域:将不同组织分割成不同区域帮助分析病情
  • 军事领域:通过对图像的分割,为自动目标识别提供参数,为飞行器或武器的精准导航提供依据
  • 遥感领域:通过遥感图像分析城市地貌、作物生长情况。此外,云系分析和天气预报都离不开图像分割
  • 交通领域:车辆跟踪和车牌识别
  • 工业领域:零部件分类、质量评估等

(3)Which(有哪些图像分割的方法)

  • 基于阈值的分割方法:利用灰度直方图得到分割的阈值,利用这些阈值将图像分为几个部分,核心思想是认为同一部分的像素是同一个物体。
  • 基于边缘的分割方法:检测图像的边界以实现对图像的分割
  • 基于区域的分割方法:核心思想是将有相似特性的像素集合起来构成区域,将差异性较大的区域进行分裂
  • 基于神经网络的分割方法:这里不多赘言,现在很火…
  • 基于聚类的分割方法:依据像素相似度,使用聚类算法将像素划分为不同类别

2.基于阈值的分割

(1)固定阈值分割

将图像分为两个部分:黑和白两个区域

/*@author @还下着雨ZG
* @brief 固定阈值图像分割
* @param[in] imSrc, 待分割的图像
* @param[out] imSegment, 分割后的图像
* @param[in] threVal, 输入的阈值
* @return, 返回正整数表示图像分割成功,负整数表示失败
**/
int ImgSegmentByGlbThreVal(const cv::Mat& imSrc, cv::Mat& imSegment, int threVal)
{if(imSrc.empty()) return -1;if(threVal<0 || threVal>255) return -2;// 图像预处理cv::Mat imGray;if(imSrc.channels()==1) imGray = imSrc.clone();else if(imSrc.channels() == 3){cv::cvtColor(imSrc, imGray, cv::COLOR_RGB2GRAY);}else{return -3;}cv::GaussianBlur(imGray, imGray, cv::Size(3,3), 0);//全局阈值法cv::threshold(imGray, imSegment, threVal);return 1;
}

阈值分割函数threshold的介绍:

double cv::threshold(cv::Mat &imSrc, //输入图像,应该为单通道cv::Mat &imDst, //分割后的图像,大小和类型和imSrc相同double thresh, //表示阈值double maxval, //最大灰度值,一般设为255int type //阈值化类型,详细介绍如下所示};

参数type的介绍:type是一个枚举类型的数据

THRESH_BINARY = 0, // ( x > thresh ) ? 255 : 0
THRESH_BINARY_INV = 1, // ( x > thresh ) ? 0 : 255
THRESH_TRUNC = 2, // ( x > thresh ) ? thresh : x
THRESH_TOZERO = 3, // ( x < thresh ) ? 0 : x
THRESH_TOZERO = 4, // ( x < thresh ) ? x : 0
THRESH_MASK = 7,
THRESH_OTSU = 8, // 自动处理,图像自适应二值化,常用区间【0-255】

(2)自适应阈值分割

根据图像不同区域的亮度分布计算局部阈值,对于图像的不同区域能够自适应计算不同阈值

void cv::adaptiveThreshold(cv::Mat &imSrc, //输入的源图像cv::Mat &imDst, //输出图像double maxval, //预设满足条件的最大值int adaptMethod, //指定自适应阈值算法类型(ADAPTIVE_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C两种)int threshType, //阈值类型(THRESH_BINARY或THRESH_BINARY_INV)int blockSize,  //领域块的大小,用于计算区域阈值(3,5,7 ...)double C, //与算法有关的参数,是一个从均值或加权均值提取的常数,可为负);

使用adaptiveThresh:

/*@author @还下着雨ZG
* @brief 自适应阈值图像分割
* @param[in] imSrc, 待分割的图像
* @param[out] imSegment, 分割后的图像
* @return, 返回正整数表示图像分割成功,负整数表示失败
**/
int ImgSegmentByAdpThre(const cv::Mat& imSrc, cv::Mat& imSegment)
{if (imSrc.empty()) return -1;cv::Mat imGray;if (imSrc.channels() == 1){cv::copyTo(imSrc, imGray, cv::Mat());}else if (imSrc.channels() == 3){cv::cvtColor(imSrc, imGray, cv::COLOR_RGB2GRAY);}else{return -2;}cv::GaussianBlur(imGray, imGray, cv::Size(3, 3), 0);int blockSize = 3;int constValue = 0;cv::adaptiveThreshold(imGray, imSegment, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, blockSize,constValue);return 1;
}

在实际使用时,大部分是先通过算子寻找边缘,然后和区域生长融合来分割图像

3.基于区域的分割

有相似特性的像素集合起来构成区域,将差异性较大的区域进行分裂

(1)分水岭算法

A.What(分水岭算法的概念)
将图像看作是测地学上的拓扑地貌,每一个像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域被称为盆地,对应得边界形成分水岭。
每一个局部极小值表面,刺穿一个小孔,然后从小孔浸水,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,两个盆地间形成分水岭。
opencv提供的分水岭算法原型如下:

void cv::watershed(cv::Mat &imBGR, //三通道8bit的彩色图像);

B.How(如何使用分水岭算法对图像进行分割)

  • step01: 图像预处理(灰度化、滤波去噪等)
  • step02: Canny边缘检测
  • step03: 查找轮廓(findContours函数查找轮廓),并把轮廓信息按照不同编号绘制到watershed的第二次参数markers上,相当于标记注水点
  • step04: watershed分水岭算法调用
  • step05: 绘制分割出来的区域
/*@author @还下着雨ZG
* @param[in] imSrc, 输入的源图像
* @param[in] imMarks, 输出图像,分割之后的结果
* @return, 正整数表示成功,负整数表示失败
*/
int ImgDvdWatershed(const cv::Mat& imSrc, cv::Mat& imMarks)
{//step01 图像预处理:灰度+滤波cv::Mat imGray;cv::Mat imGray;if (imSrc.channels() == 1){cv::copyTo(imSrc, imGray, cv::Mat());}else if (imSrc.channels() == 3){cv::cvtColor(imSrc, imGray, cv::COLOR_RGB2GRAY);}else {return -1;}cv::GaussianBlur(imGray, imGray, cv::Size(3, 3), 2); //高斯滤波//Step02 Canny边缘检测cv::Mat imEdg(imGray.size(), CV_8UC1);cv::Canny(imGray, imEdg, 40, 110);//Step03 查找轮廓并绘制轮廓std::vector<std::vector<cv::Point>> vCnts;std::vector<cv::Vec4i> hierarchy;cv::findContours(imEdg, vCnts, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);cv::Mat imContours;if (!imMarks.empty()){imMarks.release();}imMarks = cv::Mat(imGray.size(), CV_32S, cv::Scalar::all(0));int iIdx = 0;int compCount = 0;for (; iIdx >= 0; iIdx = hierarchy[iIdx][0], compCount++){cv::drawContours(imMarks, vCnts, iIdx, cv::Scalar::all(compCount + 1), 1, 8, hierarchy);cv::drawContours(imContours, vCnts, iIdx, cv::Scalar(255), 1, 8, hierarchy);}cv::Mat imRGB;if (imSrc.channels() == 1){cv::cvtColor(imSrc, imRGB, cv::COLOR_GRAY2RGB);}else if (imSrc.channels() == 3){imRGB = imSrc.clone();}//Step04 调用分水岭算法cv::watershed(imRGB, imMarks);//marks既是输入参数又是输出参数imRGB.release();return 1;
}

说明:该函数输出参数imMarks图像,同一区域用相同的数值标识,分水岭用-1标识

(2)洪水填充法分割图像

该算法通常对边缘图像进行操作,可用于分割出比较完整的外轮廓

int cv::floodFill(cv::Mat &imSrc, //输入图像cv::Point seedPt, //填充的起始点cv::Scalar newVal, //填充的像素值cv::Rect *rect=0, //将要重绘区域的最小边界矩形区域cv::Scalar loDiff = cv::Scalar(), //像素值负差的最大值cv::Scalar upDiff = cv::Scalar(), //像素值正差的最大值int flags = 4 //操作标识符);

相关文章:

计算机视觉全系列实战教程 (十二):图像分割(阈值分割threshold、分水岭算法watershed的使用步骤、洪水填充floodFill算法的使用)

1.图像分割概述 (1)What(什么是图像分割) 将图像划分为不同的子区域&#xff0c;使得同一子区域具有较高的相似性&#xff0c;不同的子区域具有明显的差异性 (2)Why(对图像进行分割有什么作用) 医学领域&#xff1a;将不同组织分割成不同区域帮助分析病情军事领域&#xff…...

Linux的免交互

交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令之后按照指令的效果做出对应的反应。 免交互&#xff1a;间接的通过第三方的方式把指令传送给程序&#xff0c;不用直接的下达指令。 1、here document免交互 ere document免交互&#xff1a;是命令…...

查看es p12证书文件过期方法

查看证书过期时间: openssl pkcs12 -in elastic-certificates.p12 -nokeys -out elastic-certificates.crt (需要输入证书生成时配置密码) openssl x509 -enddate -noout -in elastic-certificates.crt...

1.8 无符号大数加、减运算

作者 李卫明 单位 杭州电子科技大学 1.8 无符号大数加、减运算。程序设计中经常遇到无符号大数加、减运算问题&#xff0c;请在样例程序Ex1.4基础上实现无符号大数减运算。题目要求输入两个无符号大数&#xff0c;保证一个大数不小于第二个大数&#xff0c;输出它们的和、差。…...

Java常用类--包装类

包装类 一方面出于性能方面的考虑&#xff0c;java为数值使用基本类型&#xff0c;而不是对象。基本类型不是对象层次的组成部分&#xff0c;它们不继承Object。 另一方面有时需要创建表示基本类型的对象&#xff0c;例如集合类只处理对象。为了在类中存储基本类型&#xff0c;…...

SpringMvcの拦截器全局异常处理

一、拦截器 我们在网上发贴子的时候如果没有登录&#xff0c;点击发送按钮会提示未进行登录&#xff0c;跳转到登录页面。这样的功能是如何实现的。 1、 拦截器的作用 Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter&#xff0c;用于对处理器进行预处理和后处理…...

JVM虚拟机的组成

一、为什么要学习 JVM &#xff1f; 1. “ ⾯试造⽕箭&#xff0c;⼯作拧螺丝” &#xff0c; JVM 属于⾯试官特别喜欢提问的知识点&#xff1b; 2. 未来在⼯作场景中&#xff0c;也许你会遇到以下场景&#xff1a; 线上系统突然宕机&#xff0c;系统⽆法访问&#xff0c;甚⾄直…...

探索CSS clip-path: polygon():塑造元素的无限可能

在CSS的世界里&#xff0c;clip-path 属性赋予了开发者前所未有的能力&#xff0c;让他们能够以非传统的方式裁剪页面元素&#xff0c;创造出独特的视觉效果。其中&#xff0c;polygon() 函数尤其强大&#xff0c;它允许你使用多边形来定义裁剪区域的形状&#xff0c;从而实现各…...

【华为OD机试B卷】单词接龙(C++/Java/Python)

题目 题目描述 单词接龙的规则是: 可用于接龙的单词首字母必须要前一个单词的尾字母相同;当存在多个首字母相同的单词时,取长度最长的单词,如果长度也相等,则取字典序最小的单词;已经参与接龙的单词不能重复使用。现给定一组全部由小写字母组成单词数组,并指定其中的一个…...

项目实训-vue(十七)

项目实训-vue&#xff08;十七&#xff09; 文章目录 项目实训-vue&#xff08;十七&#xff09;1.概述2.问诊类型3.问诊时间统计4.看诊时间统计 1.概述 本篇博客将记录我在数据统计页面中的工作。因为项目并未实际运行&#xff0c;因此我们拟定了一些数据&#xff0c;并构建了…...

Android10 SystemUI系列 需求定制(二)隐藏状态栏通知图标,锁屏通知,可定制包名,渠道等

一、前言 SystemUI 所包含的界面和模块比较多,这一节主要分享一下状态栏通知图标和通知栏的定制需求:隐藏状态栏通知图标,锁屏通知,可定制包名,渠道等 来熟悉一下Systemui。 二、准备工作 按照惯例先找到核心类。这里提前说一下,这个需求的修改方法更多,笔者这里也只…...

Linux:RAID磁盘阵列

目录 一、RAID&#xff08;磁盘阵列&#xff09; 1.1、概念 1.2、RAID 0&#xff08;条带化存储&#xff09; 1.3、RAID 1&#xff08;镜像存储&#xff09; 1.4、RAID 5 1.5、RAID 6 1.6、RAID 10 (先做镜像&#xff0c;再做条带) 二、创建RAID 2.1、建立RAID 0 …...

MongoDB和AI 赋能行业应用:零售

欢迎阅读“MongoDB 和 AI 赋能行业应用”系列的第三篇。 本系列重点介绍 AI 应用于不同行业的关键用例&#xff0c;涵盖制造业和汽车行业、金融服务、零售、电信和媒体、保险以及医疗保健行业。 利用生成式 AI 技术&#xff08;Gen AI&#xff09;&#xff0c;零售商可以创造…...

MQ~消息队列能力、AMQP协议、现有选择(Kafka、RabbitMQ、RocketMQ 、Pulsar)

消息队列 消息队列看作是一个存放消息的容器&#xff0c;当我们需要使用消息的时候&#xff0c;直接从容器中取出消息供自己使用即可。由于队列 Queue 是一种先进先出的数据结构&#xff0c;所以消费消息时也是按照顺序来消费的。 常⽤的消息队列主要这 五 种&#xff0c;分别…...

开源网安参与编制的《代码大模型安全风险防范能力要求及评估方法》正式发布

​代码大模型在代码生成、代码翻译、代码补全、错误定位与修复、自动化测试等方面为研发人员带来了极大便利的同时&#xff0c;也带来了对安全风险防范能力的挑战。基于此&#xff0c;中国信通院依托中国人工智能产业发展联盟&#xff08;AIIA&#xff09;&#xff0c;联合开源…...

【树状数组 队列】1505. 最多 K 次交换相邻数位后得到的最小整数

本文涉及知识点 树状数组 队列 LeetCode1505. 最多 K 次交换相邻数位后得到的最小整数 给你一个字符串 num 和一个整数 k 。其中&#xff0c;num 表示一个很大的整数&#xff0c;字符串中的每个字符依次对应整数上的各个 数位 。 你可以交换这个整数相邻数位的数字 最多 k 次…...

【附精彩文章合辑】当谈到程序的“通用性”与“过度设计”的困境时,我们可以通过一些具体的例子来更直观地阐述这些解决方案

当谈到程序的“通用性”与“过度设计”的困境时&#xff0c;我们可以通过一些具体的例子来更直观地阐述这些解决方案。以下是一些示例&#xff1a; 一、明确需求与目标 例子1&#xff1a;在线购物平台 需求分析&#xff1a;平台需要支持用户注册、登录、浏览商品、下单购买、…...

Word中删除空白页

① 文字后面出现的空白页 把鼠标放在空白页的位置&#xff0c;按住Ctrl Delete即可。 ② 表格后面的空白页 把鼠标放在空白页左侧&#xff0c;直到出现一个空白的箭头&#xff0c;点击一下选中空白页&#xff0c;然后再Ctrl D&#xff0c;打开字体选项卡&#xff0c;在效果中…...

30.Netty进阶-黏包半包解决方案-短链接

客户端发送一次完整的消息,然后就把与服务端的链接断开。服务端读到的结果就是-1。 服务器就知道 从链接建立到断开,发送的数据是一条完整的数据。 客户端代码 package com.xkj.nian;import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.net…...

斜堆(数据结构篇)

数据结构之斜堆 斜堆 概念&#xff1a; 斜堆是左式堆的自调节形式&#xff0c;斜堆和左式堆间的关系类似于伸展树和AVL树间的关系斜堆是具有堆序性的二叉树&#xff0c;但是不存在对树的结构限制不同于左式堆&#xff0c;关于任意节点的零路径长的任何信息都不保留&#xff…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

[USACO23FEB] Bakery S

题目描述 Bessie 开了一家面包店! 在她的面包店里&#xff0c;Bessie 有一个烤箱&#xff0c;可以在 t C t_C tC​ 的时间内生产一块饼干或在 t M t_M tM​ 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC​,tM​≤109)。由于空间…...