分水岭算法(Watershed Algorithm)教程:硬币分割实例
import cv2
import numpy as np# 1. 图像预处理
img = cv2.imread("./water/water_coins.jpeg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
kernel = np.ones((3, 3), np.int8)
open1 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)# 2. 创建标记 (Markers)# 2.1 确定是背景的区域 (bg)
bg = cv2.dilate(open1, kernel, iterations=1)# 2.2 确定是前景的区域 (fg)
dist = cv2.distanceTransform(open1, cv2.DIST_L2, 5)
ret, fg = cv2.threshold(dist, 0.7 * dist.max(), 255, 0)# 2.3 未知区域 (unknown)
unknown = cv2.subtract(bg, fg)# 2.4 创建标记图像 (markers)
ret, markers = cv2.connectedComponents(fg)
markers = markers + 1
markers[unknown == 255] = 0# 3. 应用分水岭算法
result = cv2.watershed(img, markers)# 4. 可视化结果
img[result == -1] = [255, 0, 0]cv2.imshow("Result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
分水岭算法(Watershed Algorithm)教程:硬币分割实例
目标: 从图像中分割出多个硬币。
原理:
分水岭算法是一种基于图像形态学的分割算法。它将图像视为“地形图”,其中像素的灰度值(或颜色)代表“高度”。算法从预定义的“标记”(markers)开始“注水”,模拟水流从低洼处(标记区域)向周围蔓延的过程。当来自不同标记区域的“水”相遇时,就形成“分水岭”(watersheds),也就是分割边界。
步骤详解及关键 API 解读:
-
图像预处理:
-
读取图像并转换为灰度图:
img = cv2.imread("./water/water_coins.jpeg") # 读取图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转为灰度图-
cv2.imread(filename):- 功能: 读取图像文件。
- 参数:
filename- 图像文件的路径。 - 返回值: 一个 NumPy 数组,表示图像。如果读取失败,返回
None。
-
cv2.cvtColor(img, code):- 功能: 进行颜色空间转换。
- 参数:
img- 输入图像(NumPy 数组)。code- 颜色空间转换代码。例如:cv2.COLOR_BGR2GRAY:将 BGR 彩色图像转换为灰度图像。cv2.COLOR_BGR2RGB:将 BGR 彩色图像转换为 RGB 彩色图像。
- 返回值: 转换后的图像(NumPy 数组)。
-
-
对灰度图进行二值化处理:
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)cv2.threshold(src, thresh, maxval, type):- 功能: 对图像进行阈值处理(二值化)。
- 参数:
src- 输入图像(通常是灰度图)。thresh- 阈值。maxval- 当像素值满足阈值条件时(例如,大于阈值),赋予的新值。type- 阈值处理的类型。常用的类型包括:cv2.THRESH_BINARY:二值化。像素值大于阈值的设为maxval,小于阈值的设为 0。cv2.THRESH_BINARY_INV:反二值化。像素值大于阈值的设为 0,小于阈值的设为maxval。cv2.THRESH_TRUNC:截断。像素值大于阈值的设为阈值,小于阈值的不变。cv2.THRESH_TOZERO:像素值大于阈值的不变,小于阈值的设为 0。cv2.THRESH_TOZERO_INV:像素值大于阈值的设为 0,小于阈值的不变。cv2.THRESH_OTSU:使用大津法(Otsu’s method)自动确定最佳阈值(与前面的thresh参数一起使用,thresh通常设为 0)。
- 返回值:
ret- 实际使用的阈值(如果使用了cv2.THRESH_OTSU,则返回自动确定的阈值)。thresh- 二值化后的图像。
-
对二值化图像进行开运算(先腐蚀后膨胀):
kernel = np.ones((3, 3), np.int8) open1 = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)-
np.ones((rows, cols), dtype):- 功能: 创建一个所有元素都为 1 的 NumPy 数组。
- 参数:
rows- 行数。cols- 列数。dtype- 数据类型(例如np.uint8、np.int8、np.float32等)。
-
cv2.morphologyEx(src, op, kernel, iterations):- 功能: 执行高级形态学操作。
- 参数:
src- 输入图像。op- 形态学操作的类型。常用的类型包括:cv2.MORPH_OPEN:开运算(先腐蚀后膨胀)。cv2.MORPH_CLOSE:闭运算(先膨胀后腐蚀)。cv2.MORPH_GRADIENT:形态学梯度(膨胀 - 腐蚀)。cv2.MORPH_TOPHAT:顶帽运算(原图 - 开运算)。cv2.MORPH_BLACKHAT:黑帽运算(闭运算 - 原图)。
kernel- 结构元素(通常是一个 NumPy 数组)。iterations- 操作的迭代次数。
- 返回值: 形态学操作后的图像。
-
-
-
创建标记 (Markers):
分水岭算法需要一个初始的标记图像。标记图像中,不同的整数值表示不同的“种子”区域:
-
0: 表示“未知区域”。这些区域需要分水岭算法来确定它们属于前景还是背景。
-
1: 表示“确定是背景”的区域。
-
大于 1 的整数: 表示不同的“确定是前景”的区域(每个硬币一个标记)。
-
2.1 确定是背景的区域 (
bg):bg = cv2.dilate(open1, kernel, iterations=1)cv2.dilate(src, kernel, iterations):- 功能: 执行膨胀操作(使白色区域扩张)。
- 参数:
src- 输入图像。kernel- 结构元素。iterations- 膨胀的迭代次数。
- 返回值: 膨胀后的图像。
- 原理: 通过膨胀
open1图像, 使得硬币之间的空隙被填充, 从而得到确定的背景区域。
-
2.2 确定是前景的区域 (
fg):dist = cv2.distanceTransform(open1, cv2.DIST_L2, 5) ret, fg = cv2.threshold(dist, 0.7 * dist.max(), 255, 0)cv2.distanceTransform(src, distanceType, maskSize):- 功能: 计算图像中每个非零像素到最近零像素的距离(距离变换)。
- 参数:
src- 输入图像(通常是二值图像,非零像素表示前景,零像素表示背景)。distanceType- 距离类型。常用的类型包括:cv2.DIST_L1:曼哈顿距离(城市街区距离)。cv2.DIST_L2:欧几里得距离。cv2.DIST_C:棋盘距离。
maskSize- 距离变换的掩码大小。常用的值有 3 和 5。
- 返回值: 距离变换后的图像(灰度图像)。每个像素的值表示该像素到最近背景像素的距离。
- 原理: 硬币中心的像素距离背景最远,因此距离变换值最大。通过阈值处理,可以将这些中心区域提取出来,作为“确定是前景”的区域。
-
2.3 未知区域 (
unknown):unknown = cv2.subtract(bg, fg)cv2.subtract(src1, src2):- 功能: 从
src1图像中减去src2图像(逐像素相减)。 - 参数:
src1- 第一个输入图像。src2- 第二个输入图像。
- 返回值: 相减后的图像。
- 功能: 从
- 原理: 未知区域是指既不属于“确定是背景”也不属于“确定是前景”的区域。
-
2.4 创建标记图像 (
markers):ret, markers = cv2.connectedComponents(fg) markers = markers + 1 markers[unknown == 255] = 0-
cv2.connectedComponents(image):- 功能: 对二值图像进行连通组件标记。
- 参数:
image- 输入的二值图像(通常是“确定是前景”的图像)。
- 返回值:
ret- 连通组件的数量(不包括背景)。markers- 标记图像。每个连通区域被标记为一个唯一的整数(从 1 开始),背景标记为 0。
-
markers = markers + 1: 将标记图像中的所有值加 1。这是因为分水岭算法要求背景标记为非零值(通常为 1)。 -
markers[unknown == 255] = 0: 将未知区域的标记设置为 0。 -
处理后的
markers图像示例:1 1 1 1 1 1 1 1 (1: 背景) 1 1 1 0 0 0 1 1 (0: 未知区域) 1 1 0 2 2 2 0 1 (2: 第一个硬币的中心) 1 1 0 2 2 2 0 1 1 1 0 2 2 2 0 1 1 1 1 0 0 0 1 1 1 1 0 3 3 3 0 1 (3: 第二个硬币的中心) 1 1 0 3 3 3 0 1 1 1 1 1 1 1 1 1
-
-
-
应用分水岭算法:
result = cv2.watershed(img, markers)-
cv2.watershed(image, markers):- 功能: 应用分水岭算法进行图像分割。
- 参数:
image- 输入的原始图像(通常是彩色图像)。markers- 标记图像。
- 返回值:
result- 分割结果图像。-1:表示分割边界(watersheds)。- 其他值:表示不同的分割区域(通常与
markers中的标记值对应)。
-
result图像示例:1 1 1 1 1 1 1 1 1 1 1-1-1-1 1 1 1 1-1 2 2 2-1 1 1 1-1 2 2 2-1 1 1 1-1 2 2 2-1 1 1 1 1-1-1-1 1 1 1 1-1 3 3 3-1 1 1 1-1 3 3 3-1 1 1 1 1 1 1 1 1 1- “淹没”过程解释:
- 分水岭算法模拟“注水”过程,水流从标记区域(markers)开始向外蔓延,不同标记区域的水流相遇,形成分割边界(-1)。
- 未知区域(标记为0)相当于“无主之地”,会被相邻的标记区域的水流“淹没”,并最终归属于某个标记区域。
- “淹没”的含义是,未知区域的像素会被赋予相邻标记区域的标记值。
- 水流蔓延的方向和速度受原始图像“地形”的影响,也就是原始图像素的灰度值/颜色。
- “淹没”过程解释:
-
-
可视化结果:
img[result == -1] = [255, 0, 0] # 将分割边界标记为红色- 将原始图像中与分割边界对应的像素设置为红色,以便于观察分割结果。
总结:
分水岭算法是一种强大的图像分割工具。它通过模拟“注水”过程,结合预定义的标记图像,将图像分割成不同的区域。理解分水岭算法的关键在于:
- 标记图像: 为算法提供“种子”区域,指导算法的“注水”过程。
- “注水”过程: 模拟水流从标记区域蔓延,并在不同区域的水流相遇处形成分割边界。
- “地形”: 原始图像的灰度或颜色变化会影响“水流”的蔓延,从而影响分割边界的位置。
- 距离变换: 在硬币分割的例子中,距离变换帮助我们找到“确定是前景”的区域(硬币中心)。
相关文章:
分水岭算法(Watershed Algorithm)教程:硬币分割实例
import cv2 import numpy as np# 1. 图像预处理 img cv2.imread("./water/water_coins.jpeg") gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV cv2.THRESH_OTSU) kernel np.ones((3, 3), np.int8)…...
【STM32项目实战系列】基于STM32G474的FDCAN驱动配置
前言:本周工作中用到了CANFD的驱动,由于以前都是用到的CAN2.0,所以过程并不是特别的顺利,所以中间遇到几个比较小的问题导致自己卡住了一段时间,特此记录一下并完全奉上自己的配置的源码。 1,CANFD配置与简…...
shell文本处理
shell文本处理 一、grep 过滤来自一个文件或标准输入匹配模式内容。除了 grep 外,还有 egrep、fgrep。egrep 是 grep 的扩展,相当于 grep -E。fgrep 相当于 grep -f,用的比较少。 用法 grep [OPTION]... PATTERN [FILE]...支持的正则描述…...
如何利用客户端双向TLS认证保护云上应用安全
双向TLS(mTLS)通过要求服务器和客户端双方使用数字证书来验证彼此身份,从而扩展了传统TLS的安全性。常规的TLS只会验证服务器的身份(如大家的浏览器在验证网站时的场景),而mTLS确保在任何数据交换发生之前,双方都对彼此持有信任。在本文中&am…...
nlp第十节——LLM相关
一、模型蒸馏技术 本质上是从一个大模型蒸馏出小模型,从小模型训练出来的概率分布(如自回归模型预测下一个字的概率分布)分别与大模型预测的概率分布和ground label求loss。与大模型预测的概率分布用KL散度求loss,与ground label用…...
T-SQL 语言基础: SQL 数据库对象元数据及配置信息获取
目录 介绍目录视图 获取表和架构名称获取列信息 信息架构视图 获取表信息获取列信息 系统存储过程和函数 获取对象列表获取对象详细信息获取约束信息获取数据库属性信息 总结引用 介绍 在 SQL 数据库管理中,获取数据库对象的元数据信息是至关重要的。元数据提供了…...
ue5 创建多列StreeView的方法与理解
创建StreeView的多列样式怎么就像是创建单行单列差不多?貌似就是在单行单列中加入了多列widget? 示例代码 DetailTabWidget #pragma once #include "TreeViewItemBase.h"class SDetailTabWidget : public SCompoundWidget {SLATE_BEGIN_ARGS(SDetailT…...
C# OnnxRuntime部署DAMO-YOLO香烟检测
目录 说明 效果 模型信息 项目 代码 下载 参考 说明 效果 模型信息 Model Properties ------------------------- --------------------------------------------------------------- Inputs ------------------------- name:input tensor:Floa…...
陕西省地标-DB61/T 1121-2018 政务服务中心建设和运营规范
揭秘陕西省智慧政务服务中心新标准:打造高效便捷的服务新体验 随着信息化时代的深入发展,智慧政务已成为提升政府服务效率、优化营商环境的重要举措。陕西省作为全国政务改革的先行者,近期颁布了《陕西省地标-DB61_T 1121-2018 政务服务中心…...
UDP协议(20250303)
1. UDP UDP:用户数据报协议(User Datagram Protocol),传输层协议之一(UDP,TCP) 2. 特性 发送数据时不需要建立链接,节省资源开销不安全不可靠的协议 //一般用在实时性比较高…...
【四.RAG技术与应用】【12.阿里云百炼应用(下):RAG的云端优化与扩展】
在上一篇文章中,我们聊了如何通过阿里云百炼平台快速搭建一个RAG(检索增强生成)应用,实现文档智能问答、知识库管理等基础能力。今天咱们继续深入,聚焦两个核心问题:如何通过云端技术优化RAG的效果,以及如何扩展RAG的应用边界。文章会穿插实战案例,手把手带你踩坑避雷。…...
Docker新手入门(持续更新中)
一、定义 快速构建、运行、管理应用的工具。 Docker可以帮助我们下载应用镜像,创建并运行镜像的容器,从而快速部署应用。 所谓镜像,就是将应用所需的函数库、依赖、配置等应用一起打包得到的。 所谓容器,为每个镜像的应用进程创建…...
【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架
【星云 Orbit • STM32F4】08. 用判断数据头来接收据的串口通用程序框架 1. 引言 本教程旨在帮助嵌入式开发小白从零开始,学习如何在STM32F407微控制器上实现一个基于串口的数据接收程序。该程序能够通过判断数据头来接收一串数据,并将其存储到缓冲区中…...
HSPF 水文模型建模方法与案例分析实践技术应用
在水文模拟领域,HSPF 模型(Hydrological Simulation Program Fortran)与 SWAT 模型一样,都是备受瞩目的水文模型软件。HSPF 模型因其强大的功能和简便的操作,在全球范围内得到了广泛应用。该模型不仅能够在缺乏测量数据…...
设置 CursorRules 规则
为什么要设置CursorRules? 设置 CursorRules 可以帮助优化代码生成和开发流程,提升工作效率。具体的好处包括: 1、自动化代码生成 :通过定义规则,Cursor 可以根据你的开发需求自动生成符合规定的代码模板,…...
人工智能AI在汽车设计领域的应用探索
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活…...
《当AI生成内容遭遇审核:需求与困境的深度剖析》:此文为AI自动生成
AI 内容审核:数字时代的守门人 在当今数字技术迅猛发展的浪潮中,AI 在内容生成领域取得了令人瞩目的成就,成为了推动创新与变革的核心力量。以 AI 绘画为例,从早期简单粗糙的图像生成,到如今能够创作出细节丰富、风格多…...
【无人机与无人车协同避障】
无人机与无人车协同避障的关键在于点云数据的采集、传输、解析及实时应用,以下是技术实现的分步解析: 1. 点云数据采集(无人机端) 传感器选择: LiDAR:通过激光雷达获取高精度3D点云(精度达厘米…...
ComfyUI AnimeDiff动画参数总结
ComfyUI AnimeDiff动画参数总结 一、动画生成核心参数 参数名称建议值/范围作用说明备注步数(Steps)15-25控制AI计算迭代次数,越高细节越精细,但耗时更长推荐20步,显存不足可降至15步CFG值7.0-8.5提示词对画面的控制…...
No manual entry for printf in section 3
问题描述 在尝试查看 printf 的 C 函数手册页(即 man 3 printf)时遇到了 “No manual entry for printf in section 3” 的错误信息。 解决方案 出现这问题,是由于系统上没有安装对应的部分的手册页,因此安装对应的部分的手册…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
