Opencv学习笔记(二十一)分水岭算法

本文介绍了一种基于分水岭算法的图像分割方法,并详细解释了该算法的工作原理。通过模拟向图像中的山谷注入水的过程,算法构建堤坝来实现不同区域的分割。文中提供了完整的Python代码实现,包括预处理步骤、距离变换、标签化等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

分水岭算法

假设一副灰度图像看作是地势图,灰度值高的区域可以被看成是
山峰,灰度值低的区域可以被看成是山谷。开始向山谷中注入水,随着水位的升高,不同的山谷中的水将要汇聚,为了防止不同山谷的水汇合,我们需要在水汇合的区域构建堤坝。不停的灌水,不停的构建堤坝直至所有的山峰都被水淹没。我们构建好的堤坝就是对图像的分割。

代码

# 分水岭算法
import cv2
import numpy as np
from matplotlib import pyplot as plt
src = cv2.imread(r'F:\OPENCV\Opencv\coin.png')
if src is None:
    print('image is empty')
img = src.copy()
img = cv2.medianBlur(img, 5)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 阈值化
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)
# 形态学操作, 去除噪声
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 膨胀, 获取背景
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 距离变换
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret2, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# 获取未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)  # 不确定区域
# cv2.connectedComponents()将前景从1开始的正整数标记,背景标为0, 未知区域为-1
ret3, markers = cv2.connectedComponents(sure_fg)  # 标签化
markers = markers + 1  # 所有标签+1, 目的是将背景标签从0变为1, 因为标签为0会被算法识别为背景区域
markers[unknown == 255] = 0  # 未知区域标记为0
# cv2.watershed() 开始注水
markers2 = cv2.watershed(img, markers)

img[markers2 == -1] = [0, 0, 255]
img[markers2 >= 1] = [255, 255, 255]
# 显示结果
titles = ['src', 'gray', 'sure_bg', 'dist_transform', 'sure_fg', 'unknown', "result"]
images = [src[:, :, ::-1], gray, sure_bg, dist_transform, sure_fg, unknown, img[:, :, ::-1]]
plt.figure(1)
for i in range(len(images)):
    plt.subplot(3, 3, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.subplot(3, 3, 9)
plt.imshow(np.abs(markers), 'jet')
plt.title('markers')
plt.xticks([])
plt.yticks([])
plt.show()

结果显示
在这里插入图片描述

在这里插入图片描述

分水岭算法是一种在图像处理中常用的图像分割算法,它基于图像中的灰度和梯度信息,将图像分割成不同的区域。该算法的目标是将图像中的前景和背景分开,同时保留物体的边缘和细节。 在OpenCV中,可以使用函数cv2.watershed()实现分水岭算法。该函数接受一个灰度图像和标记图像作为输入,并将分割结果存储在标记图像中。标记图像中的像素值表示不同的区域,-1表示边界。 分水岭算法的处理流程如下: 1. 将原始图像转换为灰度图像。 2. 对灰度图像进行预处理,例如平滑和二值化,以便更好地识别前景和背景。 3. 创建一个空的标记图像,初始化为0。 4. 根据预处理后的图像,确定前景和背景的种子点。 5. 使用cv2.connectedComponents()函数将种子点标记为不同的区域,并将其存储在标记图像中。 6. 调用cv2.watershed()函数进行分水岭算法处理,将分割结果存储在标记图像中。 7. 可选步骤:根据需要进一步处理分割结果,例如绘制边界或提取特定区域的像素值。 请注意,分水岭算法需要一些预处理步骤和参数调整,以确保得到满意的分割结果。因此,在实际使用时,可能需要根据具体情况进行调整和优化。 参考资料: opencv-python——通过cv2.distanceTransform()函数将距离转换成热力图 OpenCV学习三十五:distanceTransform 距离变换函数 OPENCV自学记录(6)——连通域处理函数CV2.CONNECTEDCOMPONENTSWITHSTATS()和CV2.CONNECTEDCOMPONENTS() OpenCV3学习(7.2)——图像分割之二(分水岭算法watershed) opencv进阶学习笔记14:分水岭算法 实现图像分割图像分割分水岭算法python opencv入门 分水岭算法(29)<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [OpenCV-分水岭算法](https://blog.csdn.net/qq_43951094/article/details/120801731)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【OpenCV】- 分水岭算法](https://blog.csdn.net/qq_44859533/article/details/126436001)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值