OpenCV学习 基础图像操作(十七):泛洪与分水岭算法
原理
泛洪填充算法和分水岭算法是图像处理中的两种重要算法,主要用于区域分割,但它们的原理和应用场景有所不同,但是他们的基础思想都是基于区域迭代实现的区域之间的划分。
泛洪算法
泛洪填充算法(Flood Fill)是一种经典的图像处理算法,用于确定和标记与给定点连接的区域,通常在图像填充、分割、边界检测等方面应用广泛。为了更直观地理解泛洪填充算法,我们可以通过一系列生动的图像和步骤来介绍其工作原理。
假设我们有一个二维图像,每个像素可以有不同的颜色或灰度值。泛洪填充算法的目标是从某个起始像素开始,填充所有与其相连且具有相同颜色的像素。常见的应用包括图像编辑中的填充工具(如油漆桶工具)和迷宫求解等。
算法流程
以下是泛洪填充算法的基本步骤,配合图像说明:
-
选择起始点和目标颜色:
- 选择图像中的一个起始像素点(如鼠标点击的位置),记作 (x, y)。
- 确定要填充的目标颜色。
-
初始化队列:
- 将起始点 (x, y) 加入队列。
-
处理队列:
当队列不为空时,重复以下步骤:- 从队列中取出一个像素点 (cx, cy)。
- 如果 (cx, cy) 的颜色等于目标颜色,则进行填充。
- 将 (cx, cy) 的四个邻居(上、下、左、右)加入队列(如果这些邻居还没有被处理过且颜色等于目标颜色)。
分水岭算法
分水岭算法是一种基于形态学和拓扑学的图像分割技术。它将图像视为一个拓扑地形,通过标记图像的不同区域(例如山脉和盆地)进行分割。分水岭算法的基本思想是通过模拟雨水从山顶流向盆地的过程,确定图像中不同区域的边界。
分水岭迭代过程:
- 把梯度图像中的所有像素按照灰度值进行分类,并设定一个测地距离阈值。
- 找到灰度值最小的像素点(默认标记为灰度值最低点),让threshold从最小值开始增长,这些点为起始点。
- 水平面在增长的过程中,会碰到周围的邻域像素,测量这些像素到起始点(灰度值最低点)的测地距离,如果小于设定阈值,则将这些像素淹没,否则在这些像素上设置大坝,这样就对这些邻域像素进行了分类。
- 随着水平面越来越高,会设置更多更高的大坝,直到灰度值的最大值,所有区域都在分水岭线上相遇,这些大坝就对整个图像像素的进行了分区。
实际应用时常结合其他预处理,来实现前后景的分割:
算法流程
-
梯度计算: 首先计算图像的梯度,梯度可以使用 Sobel 算子或其他方法计算。梯度图像反映了图像中像素值变化的幅度。
其中,𝐼 是原始图像,𝐺是梯度图像。
-
标记区域: 对图像进行标记,将前景对象和背景标记出来。可以使用形态学操作来获取这些标记。
-
确定前景:使用距离变换和阈值化来确定前景区域。
-
确定背景:通过膨胀操作扩展前景区域,从而确定背景区域。
-
-
确定未知区域: 未知区域是背景和前景的差集。
-
连接组件标记: 对前景区域进行连通组件标记,每个连通组件代表一个独立的前景对象。
-
分水岭变换: 使用分水岭变换对梯度图像进行处理,分割图像中的不同区域。
分水岭变换后,标记图像的边界区域将被标记为 -1。
API介绍
floodfill
int cv::floodFill ( InputOutputArray image, //输入图像InputOutputArray mask, //输入输出的maksPoint seedPoint, //种子点Scalar newVal, //信的Rect * r ect = , 0 // 存储填充区域的边界Scalar loDiff = , Scalar() // 允许填充的像素值差的下届Scalar upDiff = , Scalar() // 允许填充的像素值差的上届int flags = 4 // 4联通或8联通
)
import cv2
import numpy as np
import matplotlib.pyplot as plt
def main():# 加载图像image_path = 'D:\code\src\code\lena.jpg' # 替换为你的图像路径image = cv2.imread(image_path)if image is None:print("Error: Unable to load image.")return# 定义种子点和新颜色seed_point = (30, 30) # 替换为你希望的种子点 (x, y)new_color = (0, 0, 255) # 新颜色为绿色 (B, G, R)# 创建掩码,比原图多出两行两列mask = np.zeros((image.shape[0] + 2, image.shape[1] + 2), np.uint8)# 设置差值范围lo_diff = (10, 10, 10)up_diff = (10, 10, 10)image_src = image.copy()# 执行泛洪填充flags = 4 # 4-连通num, im, mask, rect = cv2.floodFill(image, mask, seed_point, new_color, lo_diff, up_diff, flags)# 显示填充后的图像plt.subplot(131),plt.imshow(image_src[...,::-1]),plt.title('Source Image'), plt.xticks([]), plt.yticks([])plt.subplot(132),plt.imshow(mask[...,::-1]),plt.title('Mask Image'), plt.xticks([]), plt.yticks([])plt.subplot(133),plt.imshow(image[...,::-1]),plt.title('Filled Image'), plt.xticks([]), plt.yticks([])plt.show()if __name__ == '__main__':main()
watermeshed
cv::watershed ( InputArray image, //输入图像
InputOutputArray markers //输入出的标记
)
//即根据传入的确信区域以及原图,经过分水岭迭代后,得到的确信区域
import cv2
import numpy as np
import matplotlib.pyplot as plt
import imageiodef plot_image(image, title, save_path):plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))plt.title(title)plt.axis('off')plt.savefig(save_path)plt.close()def save_gif(frames, filename, duration=0.5):imageio.mimsave(filename, frames, duration=duration)def watershed_segmentation(image_path):# Read the imageimage = cv2.imread(image_path)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# Apply thresholdingret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)# Noise removal with morphological operationskernel = np.ones((3, 3), np.uint8)opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)# Sure background areasure_bg = cv2.dilate(opening, kernel, iterations=3)# Finding sure foreground areadist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)# Finding unknown regionsure_fg = np.uint8(sure_fg)unknown = cv2.subtract(sure_bg, sure_fg)# Marker labellingret, markers = cv2.connectedComponents(sure_fg)# Add one to all labels so that sure background is not 0, but 1markers = markers + 1# Now, mark the region of unknown with zeromarkers[unknown == 255] = 0# Apply watershedmarkers = cv2.watershed(image, markers)image[markers == -1] = [255, 0, 0] # Mark boundaries with red color# Collect frames for GIFframes = []for step in ['Original', 'Threshold', 'Morph Open', 'Sure BG', 'Sure FG', 'Unknown', 'Markers', 'Watershed']:if step == 'Original':frame = image.copy()elif step == 'Threshold':frame = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)elif step == 'Morph Open':frame = cv2.cvtColor(opening, cv2.COLOR_GRAY2BGR)elif step == 'Sure BG':frame = cv2.cvtColor(sure_bg, cv2.COLOR_GRAY2BGR)elif step == 'Sure FG':frame = cv2.cvtColor(sure_fg, cv2.COLOR_GRAY2BGR)elif step == 'Unknown':frame = cv2.cvtColor(unknown, cv2.COLOR_GRAY2BGR)elif step == 'Markers':frame = np.zeros_like(image)for i in range(1, ret + 1):frame[markers == i] = np.random.randint(0, 255, size=3)elif step == 'Watershed':frame = image.copy()frame_path = f"{step.lower().replace(' ', '_')}.png"plot_image(frame, step, frame_path)frames.append(imageio.imread(frame_path))return frames# Main execution
image_path = 'D:\code\src\code\R-C.png' # Replace with your image path
frames = watershed_segmentation(image_path)
save_gif(frames, 'watershed.gif', duration=1000)
参考链接
OpenCV(26)图像分割 -- 距离变换与分水岭算法(硬币检测、扑克牌检测、车道检测)_分水岭算法分割咖啡豆-CSDN博客
图像处理之漫水填充算法(flood fill algorithm)-腾讯云开发者社区-腾讯云 (tencent.com)
【OpenCV(C++)】分水岭算法_opencv分水岭c++-CSDN博客
相关文章:
OpenCV学习 基础图像操作(十七):泛洪与分水岭算法
原理 泛洪填充算法和分水岭算法是图像处理中的两种重要算法,主要用于区域分割,但它们的原理和应用场景有所不同,但是他们的基础思想都是基于区域迭代实现的区域之间的划分。 泛洪算法 泛洪填充算法(Flood Fill)是一…...
Docker基础命令(三)
同步docker容器中的时间和本地时间一致 背景: 在很多时候, 训练模型的时候, 记录的log日志中标记的时间和实际的时间不一致, 往往是容器时间和本地时间不一致照成的. 方案 场景一: 正在运行的容器,可以宿主机直接执行命令给某个容器同步时间 #方法1 直接在宿主机…...
Python的第三方库OS库
读者大大们好呀!!!☀️☀️☀️ 🔥 欢迎来到我的博客 👀期待大大的关注哦❗️❗️❗️ 🚀欢迎收看我的主页文章➡️寻至善的主页 文章目录 🔥前言🚀OS/SHUTIL 的方法描述🚀OS/SHUTIL…...
两个数相加减高级实现
不使用实现两数相加 #include <stdio.h> int plus(int a, int b) {int sum0,addication0;while(b!0){sum a^b;addication (a&b)<<1;a sum;b addication;}return a; }不使用-实现两数相减 #include <stdio.h> int sub(int a, int b) {int sum0,abdc…...
小白跟做江科大32单片机之对射式红外传感器计次
原理部分 1中断示意图,中断会打断主函数的执行,终端执行完成之后再返回主函数继续执行 2.STM32中断 这些灰色的是内核中断 这些白色的是普通中断 3.NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组…...
安装Kubernetes v3 ----以docker的方式部署
以docker的方式部署 docker run -d \ --restartunless-stopped \ --namekuboard \ -p 80:80/tcp \ -p 10081:10081/tcp \ -e KUBOARD_ENDPOINT"http://192.168.136.55:80" \ -e KUBOARD_AGENT_SERVER_TCP_PORT"10081" \ -v /root/kuboard-data:/data \ e…...
新游启航 失落的方舟台服注册指南 一文教会你方舟台服注册
新游启航!失落的方舟台服注册指南!一文教会你方舟台服注册 失落的方舟作为本月最受期待游戏之一,在上线之际许多玩家已经有点急不可待了。这款游戏是由开发商Smile gate开发的一款MMORPG类型游戏,这款游戏的基本玩法与其他MMORPG…...
运维开发详解
运维开发(DevOps)是开发(Development)和运维(Operations)的结合,旨在通过自动化和协作提高软件开发和交付的效率、速度和可靠性。DevOps强调文化、实践和工具的融合,以实现持续集成&…...
英伟达(NVIDIA)H100性能及应用场景
英伟达H100是一款性能强大的GPU芯片,其关键性能参数和应用领域可以归纳如下: 一、性能参数 架构:H100采用了新一代的Hopper架构,拥有高达1.8万亿次/秒的张量处理能力和高达840 TFLOPS的FP8张量性能。CUDA核心数:H100…...
充电宝怎么选?充电宝目前什么牌子质量好耐用?盘点好用充电宝
充电宝怎么选?是不是很多朋友在选充电宝上非常的纠结?在买充电宝上面还是非常有讲究的!市面上的充电宝虽然多,但是不排除很多存在安全隐患的,如果稍微没有挑选好充电宝的话,买来的充电宝极大可能是存在非常…...
智能视频监控技术为游泳馆安全护航,助力安全管理新升级
随着社会的进步和科技的发展,视频监控技术在各行各业的应用越来越广泛。游泳馆作为公共场所,每天都会有大量的游泳者进出。在这样的环境中,有时难免会发生一些意外事故,如溺水、摔倒等。因此,视频监控建设的必要性尤为…...
Windows通过cmd运行快速启动应用
Windows如何通过cmd运行快速启动应用? 在Windows操作系统中,可以通过配置环境变量的方式将文件的路径配置到环境变量的path中,配置完成后可以在cmd中输入对应的应用名称即可启动应用,具体操作如下: 1. 添加应用程序路径…...
271 基于matlab的可调Q因子小波变换故障诊断
基于matlab的可调Q因子小波变换故障诊断,可用在轴承、齿轮、活塞等故障诊断中,程序中包含了原始TQWT工具箱和轴承振动信号信号的谱包络的求取。通过仿真数据、实际轴承数据说明了方法的效果。程序已调通,可直接运行。 271 可调Q因子小波变换 …...
吴恩达深度学习个人笔记
1. 上一个视频提到的房地产领域,我们不就使用了一个普遍标准神经网络架构吗 而对于图像识别处理问题,我们则要使用卷积神经网络(Convolution Neural Network),即CNN。 对于序列数据,例如音频,有一个时间组件,随着时间的推移,音频被播放出来, 所以音频是最自然的表…...
Spring的依赖注入DI
调用构造器方法注入: 需要有对应匹配的构造器 不然出现异常No matching constructor Spring构造器注入有三种不同方式 name :按照参数名称 <bean id"stu" class"com.xja.bean.Student"> <constructor-arg name"name" value"rk&…...
Java 获取和修改期日与时间的各种操作方法
LocalDateTime获取当地日期和时间 import java.time.LocalDateTime; /*LocalDateTime.now() 获取当前时间*/ public class LocalDateTimeDemo {public static void main(String[] args) {LocalDateTime time1 LocalDateTime.now();System.out.println(time1);//2024-06-01T13…...
【ubuntu20】--- 定时同步文件
在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。 【Linux命令】--- 多核压缩命令大全&…...
网吧|基于SprinBoot+vue的网吧管理系统(源码+数据库+文档)
网吧管理系统 目录 基于SprinBootvue的网吧管理系统 一、前言 二、系统设计 三、系统功能设计 1 管理员功能模块 2 网管功能模块 3 会员功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍&#…...
[C/C++] -- Libcurl开发
libcurl 是一个功能强大的 C 语言库,用于实现各种网络传输协议的客户端功能。它是 Curl 工具的核心,并提供了一个简单、灵活、高效的 API,允许开发人员在他们的应用程序中轻松地执行网络操作。 以下是 libcurl 的一些主要特点和功能…...
Streamsets-JDBC模式使用更新时间字段数据同步
StreamSets的开源地址:https://github.com/streamsets/datacollector-oss Streamsets官网地址:https://streamsets.com/ Streamsets文档地址:https://docs.streamsets.com/portal/datacollector/3.16.x/help/index.html 我又来写Streamsets了…...
Nodejs-- 网络编程
网络编程 构建tcp服务 TCP tcp全名为传输控制协议。再osi模型中属于传输层协议。 tcp是面向连接的协议,在传输之前需要形成三次握手形成会话 只有会话形成了,服务端和客户端才能想发送数据,在创建会话的过程中,服务端和客户…...
React@16.x(14)context 举例 - Form 表单
目录 1,目标2,实现2.1,index.js2.2,context.js2.2,Form.Input2.3,Form.Button 3,使用 1,目标 上篇文章说到,context 上下文一般用于第3方组件库,因为使用场景…...
十几款基于ChatGPT的免费神器,每个都是王炸!
十几款基于ChatGPT的免费神器,每个都是王炸! 1、ChatGPT ChatGPT非常强大,但注册需要魔法和国外的手机号,大部分人都没法使用。还好有一些基于API开发的体验版,我收集了一些可以直接使用的站点分享给大家,…...
devicemotion 或者 deviceorientation在window.addEventListener 事件中不生效,没有输出内容
问题:devicemotion 或者 deviceorientation 在window.addEventListener 事件中不生效,没有输出内容 原因: 1、必须在Https协议下才可使用 2、必须用户手动点击click事件中调用 ,进行权限申请 源码: <!DOCTYPE h…...
java单元测试如何断言异常
在junit单元测试中,我们可以使用 org.junit.Assert.assertThrows 包下的 assertThrows() 方法 这个方法返回了一个泛型的异常 public static <T extends Throwable> assertThrows(Class<T> expectedType, Executable executable) 假设我们有以下…...
C语言| n的阶乘相加
逻辑性较强,建议记住。 分析思路: 假如n4:m m * i; sum sum m; 1)当i1时,m1, sum1。 2)当i2时,m12, sum112。 3)当i3时,m123, sum112123。 4)当i4时&…...
cwiseMax、cwiseMin函数
一、cwiseMax含义 cwiseMax是Eigen库中的一个函数,用于求两个矩阵或向量的逐元素最大值。它的作用类似于std::max函数,但是可以同时处理多个元素,且支持矩阵和向量。 举例: 例如,对于两个向量a和b,cwiseMax…...
【thinkphp问题栏】tp5.1重写URL,取消路径上的index.php
在Apache运行thinkphp5.1时,发现系统默认生成的.htaccess不生效。 首先先查看怎么修改伪静态 1、修改Apache的配置文件 在Apache的安装目录下,打开config/httpd.conf。 搜索rewrite.so,将前面的#删掉,表示开启URL重写功能 2、…...
缓冲字符流
BufferedReader/BufferedWriter增加了缓存机制,大大提高了读写文本文件的效率。 字符输入缓冲流 BufferedReader是针对字符输入流的缓冲流对象,提供了更方便的按行读取的方法:readLine();在使用字符流读取文本文件时,我们可以使…...
Django中使用Celery和APScheduler实现定时任务
在之前的文章我们已经学习了Celery和APScheduler的基本使用,下面让我们来了解一下如何在Django中使用Celery和APScheduler Celery 1.前提工作 python 3.7 pip install celery pip install eventlet #5.0版本以下 pip install importlib-metadata4.8.3(…...
Kivy.uix.textinput
一个小小的输入框,纵上下数页文档已不能全不概括,当去源码慢慢寻找,才知道其中作用,才能运用灵活。 Text Input — Kivy 2.3.0 documentation # -*- encoding: utf-8 -*-Text Input .. versionadded:: 1.0.4.. image:: images/te…...
基于IoTDB 平台的学习和研究
Apache IoTDB(物联网数据库)是一个针对物联网领域的高性能原生数据库,适用于数据管理和分析,并可在边缘计算和云端部署。由于它轻量级的架构、高性能和丰富的功能集,以及与Apache Hadoop、Spark和Flink的深度集成&…...
nessus plugins目录为空的问题
想要避免这种问题,可以将nessus服务设置为手动,并且先停止nessus服务。 批处理脚本: 下面的/~/Nessus/plugin_feed_info.inc替换成你配置好的 plugin_feed_info.inc 所在的路径 service nessusd stop; cp /~/Nessus/plugin_feed_info.inc …...
FDW(Foreign Data Wrapper)
在上一篇博客里,最末尾提到了 FDW。pg 实现了数百个 fdw 插件,用于访问外部数据。 FDW 到底是什么呢? 标准 FDW(Foreign Data Wrapper)遵循了 SQL/MED 标准,标准全称:ISO/IEC 9075-9 Managem…...
Flutter开发指南
Flutter开发指南(Android 开发角度) 与Android 的对比 1.Android 的View 与Flutter 的对应关系: a.在android 中,view 是屏幕显示的基础,比如 button,文本,列表,输入框都是 view。…...
SpringCloud学习笔记万字整理(无广版在博客)
在此感谢黑马程序员的SpringCloud课程 所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验(无广告且清爽),请访问本篇笔记 认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐…...
c++(七)
c(七) 内联函数内联函数的特点为什么要有内联函数内联函数是如何工作的呢 类型转换异常处理智能指针单例模式懒汉模式饿汉模式 VS中数据库的相关配置 内联函数 修饰类的成员函数,关键字:inline inline 返回值类型 函数名(参数列…...
SQL语言
SQL语言 导航 文章目录 SQL语言导航一、SQL概述SQL 二、数据库定义SQL 数据类型 三、数据操作视图更新 四、SQL的授权五、存储过程六、嵌入式SQL主语言与数据库通信 七、动态SQL 一、SQL概述 SQL 支持三级模式结构 视图->外模式 基本表->模式 存储文件->内模式 二…...
【PPT】修改新建文本框默认字体
【PPT】修改新建文本框默认字体...
智能办公本如何选择
智能办公本如何选择 引言 随着科技的不断发展,智能办公本已成为现代职场人士的重要工具。它们不仅具备传统纸质笔记本的书写体验,还融入了先进的智能技术,让办公变得更加高效便捷。在选择智能办公本时,我们需要关注多个方面&…...
Spark基础:Scala变量与数据类型
在Scala中,变量和数据类型是编程的基础。Scala作为一种强大的静态类型语言,支持多种数据类型,并提供了可变(var)和不可变(val)两种类型的变量声明方式。以下是在Scala中变量和数据类型的基础知识…...
php 实现:给图片加文字水印,图片水印,压缩图片
演示环境: 1、windows10 2、phpstudy 3、php7.4 一、案例演示: 二、素材准备 1、准备一张原始图片 2、准备一张水印图片(透明底图的最好) 3、字体库(windows系统自带的字体库,路径在:C:\Window…...
免费实现网站HTTPS访问
HTTPS(Hypertext Transfer Protocol Secure)是一种基于SSL协议的HTTP安全协议,旨在为客户端(浏览器)与服务器之间的通信提供加密通道,确保数据在传输过程中的保密性、完整性和身份验证。与传统的HTTP相比&a…...
vue3使用vue3-print-nb打印
打印效果 1.下载插件 Vue2.0版本安装方法 npm install vue-print-nb --saveVue3.0版本安装方法: npm install vue3-print-nb --save2.main.js引入 vue2引入 import Print from vue-print-nb Vue.use(Print)vue3引入 import print from vue3-print-nb // 打印…...
R语言ggplot2包绘制网络地图
重要提示:数据和代码获取:请查看主页个人信息!!! 载入R包 rm(listls()) pacman::p_load(tidyverse,assertthat,igraph,purrr,ggraph,ggmap) 网络节点和边数据 nodes <- read.csv(nodes.csv, row.names 1) edges…...
php获取今天凌晨零点的时间
不废话直接上代码 //使用strtotime $midnightToday strtotime("today midnight"); //输出:1716998400 //如果是明天 $midnightToday 86400 //后天 $midnightToday 86400*2//ORM中比对使用 $row ModelVisit::where(uid,$this->uid)->where(visi…...
CATIA进阶操作——创成式曲面设计入门(1)线架设计,三维点、直线、平面、曲线
目录 引出三维空间点生成三维直线三维平面三维曲线总结异形弹簧新建几何体草图编辑,画一条样条线进行扫掠,圆心和半径画出曲面上的螺旋线再次选择扫掠,圆心和半径 其他自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重…...
thinkphp6中怎么查看ThinkPHP版本号
<?php namespace app\controller; use app\BaseController; use think\app; //这句 class Index extends BaseController { public function test() { echo App::VERSION; //还有这句 } }...
第十二章 创建Web客户端
文章目录 第十二章 创建Web客户端SOAP向导的概述使用SOAP向导 第十二章 创建Web客户端 web客户端是访问web服务的软件。web客户端提供了一组代理方法,每个方法对应于web服务的一个方法。代理方法使用与它所对应的web服务方法相同的签名,并在被请求时调用…...
调试记录-RK平台用指令开启ADB功能
需求 嵌入式Linux系统调试过程中,为了方便,我们会借鉴Android调试的方法,在Linux系统添加adb功能,主要功能是通过USB线连接开发板和PC,实现两者之间传输文件,在PC上执行指令操作开发板。 实现 前提&…...