0
点赞
收藏
分享

微信扫一扫

【OpenCV-Python】教程:3-15 分水岭图像分割

陆佃 2022-12-07 阅读 151

OpenCV Python 分水岭图像分割

【目标】

  • 学习使用分水岭方法进行基于标记的图像分割
  • cv2.watershed()

【理论】

任何灰度图像都可以被视为地形表面,其中高强度表示山峰和丘陵,而低强度表示山谷,。你开始用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。随着水的上升,根据附近山峰(梯度),来自不同山谷的水,显然具有不同的颜色,将开始融合。为了避免这种情况,你需要在水汇合的地方建造障碍物,你继续注水和建造屏障,直到所有山峰都淹没在水下,然后,您创建的障碍会给出分割结果。这就是分水岭别后的“哲学”,您可以访问分水岭上的网页看动画,如下:

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

  • 分割的流程图

在这里插入图片描述

  1. 找到标记和分割标准(标准或函数常用于分离区域,常常是对比度或梯度,但不是必要的。
  2. 执行标记控制的分水岭算法。

【代码】

利用距离变换和分水岭分割黏在一起的目标。

在这里插入图片描述

在这里插入图片描述

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

# 读入图像
img = cv2.imread('assets/water_coins.jpg')
gray = cv2.imread('assets/water_coins.jpg', 0)

# 阈值化
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)

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

# 通过距离变换,然后阈值化找前景
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
# 这个地方的阈值(0.5 * dist_transform.max())调节很重要,直接关系到后面的分割效果
ret, sure_fg = cv2.threshold(dist_transform, 0.5 * dist_transform.max(), 255, cv2.THRESH_BINARY)

# 计算未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

# 标记连通区域
ret, markers = cv2.connectedComponents(sure_fg)

# 所有的标记+1,背景改为1,而不是0
markers = markers + 1

# # 标记不确定区域为0
markers[unknown==255] = 0

# 用分水岭方法找到标记,如果标记为 -1,则该位置设置蓝色,即边缘颜色
markers = cv2.watershed(img, markers)
img[markers == -1] = [255, 0, 0]

# 显示分割的图像
image2 = np.uint8(img)
cv2.imshow("img2", image2)

# 显示各阶段的图像
plt.subplot(231), plt.imshow(gray, 'gray'), plt.title(
    'Original'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(sure_bg, 'gray'), plt.title(
    'sure_bg'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(sure_fg, 'gray'), plt.title(
    'sure_fg'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(dist_transform), plt.title(
    'dist_transform'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(markers), plt.title(
    'markers'), plt.xticks([]), plt.yticks([])
plt.subplot(236), plt.imshow(img), plt.title(
    'img'), plt.xticks([]), plt.yticks([])
plt.show()

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

在这里插入图片描述

【接口】

  • distanceTransform
cv.distanceTransform(	src, distanceType, maskSize[, dst[, dstType]]	) ->	dst
cv.distanceTransformWithLabels(	src, distanceType, maskSize[, dst[, labels[, labelType]]]	) ->	dst, labels
  • distanceType 距离类型

在这里插入图片描述

  • DistanceTransformMasks 距离变换mask

在这里插入图片描述

  • DistanceTransformLabelTypes 距离变换标签类型

在这里插入图片描述

  • connectedComponents
cv.connectedComponents(	image[, labels[, connectivity[, ltype]]]	) ->	retval, labels

cv.connectedComponentsWithAlgorithm(	image, connectivity, ltype, ccltype[, labels]	) ->	retval, labels
  • ConnectedComponentsAlgorithmsTypes

在这里插入图片描述

  • watershed
cv2.watershed(	image, markers	) ->	markers

【参考】

  1. OpenCV 官方文档
  2. CMM page on Watershed Transformation
  3. Pedro Felzenszwalb and Daniel Huttenlocher. Distance transforms of sampled functions. Technical report, Cornell University, 2004.
  4. Gunilla Borgefors. Distance transformations in digital images. Computer vision, graphics, and image processing, 34(3):344–371, 1986.
  5. Federico Bolelli, Stefano Allegretti, Lorenzo Baraldi, and Costantino Grana. Spaghetti Labeling: Directed Acyclic Graphs for Block-Based Connected Components Labeling. IEEE Transactions on Image Processing, 29(1):1999–2012, 2019.
  6. Costantino Grana, Daniele Borghesani, and Rita Cucchiara. Optimized Block-Based Connected Components Labeling With Decision Trees. IEEE Transactions on Image Processing, 19(6):1596–1609, 2010.
  7. Kesheng Wu, Ekow Otoo, and Kenji Suzuki. Optimizing two-pass connected-component labeling algorithms. Pattern Analysis and Applications, 12(2):117–135, Jun 2009.
  8. Fernand Meyer. Color image segmentation. In Image Processing and its Applications, 1992., International Conference on, pages 303–306. IET, 1992.
举报

相关推荐

0 条评论