opencv-分水岭算法分割

原理
任何一副灰度图像都可以被看成拓扑平面,灰度值高的区域可以被看成是山峰,灰度值低的区域可以被看成是山谷。我们向每一个山谷中灌不同颜色的水。随着水的位的升高,不同山谷的水就会相遇汇合,为了防止不同山谷的水汇合,我们需要在水汇合的地方构建起堤坝。不停的灌水,不停的构建堤坝知道所有的山峰都被水淹没。我们构建好的堤坝就是对图像的分割。这就是分水岭算法的背后哲理。
分水岭算法是一种图像分割算法,常用于分割具有重叠目标的图像。它基于数学形态学的理念,将图像看作地形图,水流在图像的低谷(目标边界)聚集,形成分割线。OpenCV 提供了 cv2.watershed() 函数来执行分水岭算法。

基本的语法如下:

cv2.watershed(image, markers)

参数说明:

  • image: 输入的图像,通常是一个三通道彩色图像。
  • markers: 标记图像,用于指定分水岭算法的初始标记。标记图像应该是单通道灰度图像,其中不同的标记值表示不同的区域。

cv2.watershed 函数会修改输入图像,将标记图像中的区域分割开,并用不同的颜色标记不同的分割区域。分水岭算法通常用于从预先标记的图像中分割出目标区域。

以下是一个简单的示例,演示如何使用分水岭算法进行图像分割:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
img = cv2.imread(r"C:\Users\mzd\Desktop\opencv\4.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 使用阈值分割获取前景区域掩码
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
#cv2.threshold 是 OpenCV 中用于图像阈值化的函数。阈值化是一种将图像分割成两个区域的方法,通常用于目标检测、边缘检测等应用。
# 对前景区域进行形态学操作,消除小的噪点
kernel = np.ones((3, 3), np.uint8)
#np.ones 是 NumPy 中的一个函数,用于创建一个指定形状(shape)的数组,并将数组的所有元素初始化为 1
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# 通过距离变换获取图像的距离变换结果
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

# 获取背景区域掩码
sure_bg = cv2.dilate(opening, kernel, iterations=3)

# 标记不确定的区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

# 使用连通组件标记不确定区域
_, markers = cv2.connectedComponents(sure_fg)

# 将标记+1作为不确定区域的标记,以避免与已知区域的标记冲突
markers = markers + 1
markers[unknown == 255] = 0  # 不确定区域的标记设为0

# 应用分水岭算法
cv2.watershed(img, markers)

# 将分水岭算法的标记区域设为红色
img[markers == -1] = [255, 0, 0]

# 显示原始图像、阈值分割结果和分水岭算法结果
plt.figure(figsize=(12, 6))

plt.subplot(131), plt.imshow(img_rgb)
plt.title('Original Image'), plt.axis('off')

plt.subplot(132), plt.imshow(thresh, cmap='gray')
plt.title('Thresholded Image'), plt.axis('off')

plt.subplot(133), plt.imshow(img)
plt.title('Watershed Result'), plt.axis('off')

plt.show()

在这里插入图片描述

在这个示例中,我们首先读取了一幅图像,将其转换为灰度图像。然后,使用阈值分割获取前景区域的掩码,并通过形态学操作和距离变换对图像进行预处理。接着,通过分水岭算法将图像分割为不同的区域,并在结果图像上标记分割线。最后,通过 Matplotlib 显示原始图像、阈值分割结果和分水岭算法的分割结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI自修室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值