3. 基于分水岭的算法的图像分割

基于分水岭算法的图像分割

一、理论

  任何灰度图像都可以看作是地形表面,其中高强度的表示峰和丘陵,而低强度的表示山谷。用不同颜色的水(标签)填充每个孤立的山谷(局部最小值)。水位上升取决于附近的峰值(梯度),来自不同山谷的水将开始融合,为避免这种情况,需要在水合并前建立障碍,继续填补水和建立障碍的工作,直到所有的山峰都在水下。

  这种方法会因图像中的噪声或任何其他不规则形而给出过度调整结果。因此,OpenCV 提供了基于标记的分水岭算法,可以指定哪些谷点要合并,哪些不合并。这是一种交互式图像分割。

二、利用分水岭算法分割硬币

在这里插入图片描述

  首先找到硬币的近似估计值,为此。可以使用Otsu 的二值化

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

img = cv.imread('E:/Computer/Desktop/opencv/Image_watershed_coins.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
plt.imshow(thresh, cmap='gray')

在这里插入图片描述

  现在需要去除图像中的任何小白噪声,为此,可以使用图像开运算,移除对象中的小孔,可以使用图像闭运算。所以,限制我们知道了靠近物体中心的区域是前景,而远离物体的区域是背景。

  所以我们需要提取我们确定他们是硬币的区域,侵蚀消除了边界像素。

kernel = np.ones((3, 3), np.uint8)
opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2)
plt.imshow(opening, cmap='gray')

在这里插入图片描述

sure_bg = cv.dilate(opening, kernel, iterations=3)
dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)
ret, sure_fg = cv.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
unknow = cv.subtract(sure_bg, sure_fg)
plt.subplot(211)
plt.imshow(unknow)
plt.subplot(212)
plt.imshow(sure_fg)

在这里插入图片描述

  边界通过sure_bg区域中减去sure_fg区域获得。在阈值图像中,得到了一些我们确定硬币的硬币区域,现在他们已经分离。

  现在确定哪个是硬币区域,哪个是背景。所以创建标记并标记其中的区域。我们确切的知道任何区域都标有不同的正整数,不确定的区域保留为0,对此,使用cv.connectedComponents()。它用0标记图像背景,用1开始的整数标记其他对象。

  但是,如果背景标记为0,分水岭会将其视为未知区域,所以要用不同的整数来标记他。相反,将标记有未知定义的位置区域标记为0。

markers = cv.watershed(img, markers)
img[markers == -1] = [255, 0, 0]
plt.subplot(121)
plt.imshow(markers)
plt.subplot(122)
plt.imshow(img)

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值