【图像分割】传统分割算法—分水岭算法(包含基于opencv的实例展示)

一、分水岭算法原理

分水岭算法将图像看作地理学中的地形表面,图像中的高灰度值区域被看作山峰,低灰度值区域被看作山谷。进而实现图像的分割。

在这里插入图片描述

在这里插入图片描述

假如我们向“山谷”中注水,水位则会逐渐升高,然后不同山谷的水就会汇集在一起,如果我们阻止来自不同山谷的水汇集,我们需在水流可能交汇处建立堤坝,我们需要把图像分成两个不同的集合:集水盆地和分水岭线。我们建立的堤坝即是分水岭线,也即是对原图像的分割。
在这里插入图片描述
在这里插入图片描述

但是由于图像中的噪声或任何其他不规则性,这种方法会造成过度分割的结果。所以OpenCV实现了一种基于标记的分水岭算法,您可以指定哪些是所有要合并的山谷点,哪些不是。这是一种交互式图像分割。我们所做的是为我们知道的对象给出不同的标签。用一种颜色(或强度)标记我们确定是前景或对象的区域,用另一种颜色标记我们确定是背景或非对象的区域,最后用0标记我们不确定的区域。这就是我们的标记。然后应用分水岭算法。然后我们的标记将使用我们给出的标签进行更新,并且对象的边界将具有-1的值。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、利用opencv实现分水岭算法的步骤:

  1. 找到图像前景的近似估计,可以使用Otsu的二值化。
  2. 通过形态学开运算实现原始图像O的去噪。
  3. 通过膨胀操作获取“确定背景B"。
  4. 利用距离变换函数cv2.distanceTransform()对图像进行处理,并对其结果进行阈值分割,得到”确定前景F“。
  5. 计算未知区域UN。UN=O-B-F
  6. 利用cv.connectedComponents()实现原始图像O的标注工作。
  7. cv.connectedComponents()的标注结果进行修正。
  8. 使用分水岭分割函数cv.watershed()完成对图像的分割。

三、算法实例

下面我们以下图相接触的硬币图像为例,分割获取硬币的范围。

在这里插入图片描述

1.获取硬币的近似估计

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('coins.png')
assert img is not None, "file could not be read, check with os.path.exists()"
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)

在这里插入图片描述

2.图像去噪

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)

在这里插入图片描述

3.确定背景区域

# sure background area
sure_bg = cv.dilate(opening,kernel,iterations=3)

在这里插入图片描述

4.确定前景区域

# Finding sure foreground area
dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)
ret, sure_fg = cv.threshold(dist_transform,0.7*dist_transform.max(),255,0)

在这里插入图片描述

5.确定未知区域

# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg,sure_fg)

在这里插入图片描述

6.实现图像标注以及修复处理

# Marker labelling
ret, markers = cv.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0

在这里插入图片描述

7.应用分水岭算法实现分割

markers = cv.watershed(img,markers)
# The boundary region will be marked with -1.
img[markers == -1] = [255,0,0]

在这里插入图片描述

注意:以上方法中通过距离函数确定未知区域是针对物体相互接触的情况,对于物体独立,没有相互接触的情况,可以在膨胀操作后,进行腐蚀操作,然后前者减去后者,即得到未知区域:

sure_bg = cv2.dilate(opening, kernel, iterations=3)  # sure background area
sure_fg = cv2.erode(opening, kernel, iterations=3)  # sure foreground area
unknown = cv2.subtract(sure_bg, sure_fg)  # unknown area
  • 5
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于分水岭算法图像分割是一种常用的图像处理技术,可以将图像分割成多个区域,每个区域内的像素具有相似的特征。在 OpenCV 中,可以使用 cv2.watershed() 函数实现基于分水岭算法图像分割。 下面是一个简单的 Python 示例,演示如何使用基于分水岭算法图像分割: ```python import cv2 import numpy as np # 读取图像 img = cv2.imread('image.jpg') # 转换为灰度图像 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.uint8) opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel,iterations=2) # 距离变换 dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5) ret, sure_fg = cv2.threshold(dist_transform,0.1*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) # 标记连通区域 ret, markers = cv2.connectedComponents(sure_fg) markers = markers + 1 markers[unknown==255] = 0 # 应用分水岭算法 markers = cv2.watershed(img,markers) img[markers == -1] = [255,0,0] # 显示结果 cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在上面的示例中,首先读取一张图像,并将其转换为灰度图像。然后使用阈值分割算法将图像二值化。接下来,进行形态学操作,以去除图像中的噪声。然后使用距离变换算法计算前景区域,并将其阈值化。接着,使用形态学操作计算背景区域。最后,使用 cv2.connectedComponents() 函数计算不确定区域,并使用标记连通区域的方法生成分水岭算法的输入标记图像。最后,应用 cv2.watershed() 函数进行图像分割,并在窗口中显示结果。 需要注意的是,分水岭算法的结果依赖于输入标记图像的质量,因此需要根据具体情况进行调整,比如阈值分割的参数、形态学操作的参数、距离变换的参数等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

卖报的大地主

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

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

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

打赏作者

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

抵扣说明:

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

余额充值