怎么在python中使用opencv实现一个分水岭算法

  

今天就跟大家聊聊有关怎么在python中使用opencv实现一个分水岭算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

目标

  1. 使用分水岭算法对基于标记的图像进行分割

  2. 使用函数cv2.watershed()

原理:

灰度图像可以被看成拓扑平面,灰度值高的区域可以看出山峰,灰度值低的区域可以看成是山谷。向每一个山谷当中灌不同颜色的水。水位升高,不同山谷的水会汇合,为防止不同山谷的水汇合,小在汇合处建立起堤坝。然后继续灌水,然后再建立堤坝,直到山峰都掩模。构建好的堤坝就是图像的分割。

此方法通常会得到过渡分割的结果,因为图像中的噪声以及其他因素。为了减少此影响,opencv使用基于标记的分水岭算法,此算法要设置哪些山谷中的汇合点,哪些不是。这是一种交互式的图像分割算法那。我们要给已知对象打上不同表情。如果某个区域肯定是前景或对象,就使用某个颜色或灰度值标签标记它。如果是背景那么使用其他颜色进行标记,其余不能确定的部分用0标记。然后使用分水岭算法,每次灌水,标签会被更新,当两个不同颜色的标签相遇就会构建堤坝,知道所有山峰掩模,最后得到的边界对象值是-1。

代码:

对挨在一起的对象进行分割。

怎么在python中使用opencv实现一个分水岭算法

使用Otsu's 二值化后的结果为

怎么在python中使用opencv实现一个分水岭算法

要出去图像中的白噪声。可以使用形态学运算,使用闭运算去除对象中的空洞。

靠近对象中心的区域是前景,离对象远的区域是背景,不确定的区域是边界。

首先提取硬币区域,使用腐蚀操作去掉边缘,剩下的就是硬币。但硬币没有接触时,此方法有效,但是由于硬币相互接触,就要使用另外一种有效的方法:距离变换加上合适的阈值。

之后,要寻找不确定是否是硬币的区域。这里需要膨胀操作。膨胀操作会将对象边界延伸到背景当中。由于边界区域被去除,现在就能知道哪些区域是前景,哪些是背景。

余下的区域不知道如何区分,那么使用分水岭算法。这些区域通常是前景与背景的交界处。从能否确认是否是背景的区域中减去确定是前景的区域就得到了边界。

(前景和背景)

怎么在python中使用opencv实现一个分水岭算法

(上面的图是直接使用作者的代码后生产的结果,提取到了前景,为了演示一下不确定的区域,调了一下计算前景的距离变换的参数,使得中间出现不确定的区域)

怎么在python中使用opencv实现一个分水岭算法

这里面使用个cv2.distanceTransform函数

该函数用于计算二值图象中所有像素离其最近的值为0像素的近似距离。

参数为

cv2.distanceTransform (src, distanceType,, maskSize [, dst]),→dst      # src为输入的二值图像.distanceType为计算距离的方式,可以是如下值   DIST_USER =,⑴,,//! & lt; User  defined 距离   DIST_L1 ,=,,,//! & lt;, distance =, | x1, x2) |, +, | y1 y2 |   DIST_L2 ,=,,,//! & lt;从而simple  euclidean 距离   DIST_C ,=,,,//! & lt;, distance =,马克斯(| x1, x2), | | y1 y2 |)   DIST_L12 ,=,,,//! & lt;, L1-L2 度量:,distance =, 2 (sqrt (1 + x * x/2),安康;1))   时间=DIST_FAIR  5,,//! & lt;, distance =, c ^ 2 (| | x/c log (1 + | | x/c)), c  1.3998=,   DIST_WELSCH =, 6,,//! & lt;, distance =, c ^ 2/2 (1-exp (- (x/c) ^ 2)), c  2.9846=,   DIST_HUBER =, 7,//! & lt;, distance =, | x | & lt; c  ?, x ^ 2/2 :, c (x | | - c/2), c=1.345         # maskSize是蒙板尺寸,只有0、3、5   DIST_MASK_3 ,=,,,//! & lt;面具=3   DIST_MASK_5 ,=,,,//! & lt;面具=5   DIST_MASK_PRECISE =, 0,//! & lt;,面具=0 import  numpy  as  np   import  cv2   得到matplotlib  import  pyplot  as  plt   时间=img  cv2.imread (& # 39; 21. jpg # 39;)   时间=gray  cv2.cvtColor (img cv2.COLOR_BGR2GRAY)   ret, thresh =, cv2.threshold(灰色,0255年,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)      时间=kernel  np.ones ((3,3), np.uint8)   opening =, cv2.morphologyEx(打、cv2.MORPH_OPEN内核,iterations =, 2)   #,sure  background 区域   时间=sure_bg  cv2.dilate(开放、内核、迭代=3)#膨胀   #,Finding  sure  foreground 区域      时间=dist_transform  cv2.distanceTransform(开放1 5)   ret, sure_fg =, cv2.threshold (dist_transform 0.2 * dist_transform.max(), 255年,0)#参数改小了,出现不确定区域   #,Finding  unknown 地区   时间=sure_fg  np.uint8 (sure_fg)   时间=unknown  cv2.subtract (sure_bg sure_fg) #减去前景      cv2.imshow (& # 39; p # 39;, sure_fg)   cv2.waitKey (0)

怎么在python中使用opencv实现一个分水岭算法