引言
进行图像的分割的方式有很多种,这里我们主要要介绍的是一种叫做分水岭(Watershed)的算法。
介绍
与GrabCut算法不同的是,GrabCut算法的实现步骤是: (1)图片中定义(一个或者多个)物体的矩形。 (2)矩形外的区域被自动认为是背景。(先假设) (3)对于矩形区域内,可以用背景中的数据来区别它里面的前景和背景区域。 (4)之后我们用高斯混合模型(Gaussians Mixture Model,GMM)来对背景和前景建模,并将未定义的像素标记为可能的前景或背景。 (5)图像中的每一个像素都被看做通过虚拟边与周围像素相连接,而每条边都有一个属于前景或背景的概率,这基于它与周围像素颜色上的相似性。(这个与图论中的连接一致) (6)每一个像素(即算法中的节点)会与一个前景或背景节点进行连接。 (7)在节点完成连接后(可能与前景或背景相连接),若节点之间的边属于不同终端(即:一边是前景一边是背景)则会切断他们的边,从而将图像各部分分割出来。(构成不同的连通分支) 而在分水岭算法中,我们需要将图像中低密度的区域(颜色变化很小的区域)想象成山谷的形状,之后再将图像中高密度的区域(颜色变化程度大的区域)想象成山峰。 之后我们开始“向山谷中注水”,直到不同山谷中的水开始汇聚,为了阻止水汇聚,可以设置一些栅栏,最后得到的栅栏就是我们图像分割的结果。 给不同山谷的水不同颜色的水,水涨起来后,不同颜色的水会有合并的趋势,为了阻止这种情况的发生,我们需要加上栅栏,而我们加上的栅栏就是最后的分割。
案例
之后我们来进行实例的分析,我们用下图来进行分水岭算法的实现。
import numpy as np
import cv2
img=cv2.imread('1.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
cv2.imshow('img1',thresh)
结果如图所示:
kernel = np.ones((3,3),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)
cv2.imshow('img2',opening)
其结果如下图所示:
sure_bg = cv2.dilate(opening,kernel,iterations=3)
cv2.imshow('img3',sure_bg)
dist_transform = cv2.distanceTransform(opening,cv2.DIST_L2,5)
cv2.imshow('img4',dist_transform)
ret, sure_fg = cv2.threshold(dist_transform,0,255,0)
cv2.imshow('img5',sure_fg)
其结果为如图所示:
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg,sure_fg)
cv2.imshow('img6',unknown)
结果如图所示:
ret, markers = cv2.connectedComponents(sure_fg)
# 所有像素值+1
markers = markers+1
# 这里将所有未知区域的像素设置为0
markers[unknown==255] = 0
# 打开门,让水漫起来
markers = cv2.watershed(img,markers)
# 将原图中的栅栏位置的颜色设置为蓝色并进行显示
img[markers == -1] = [255,0,0]
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
最后我们的结果图如下图所示。
总结
正如我们开头的时候所说的,所有的灰度图像都可视为拓扑平面,灰度值高的区域看成山峰,灰度值低的区域看成山谷,我们向图像上所有的“山谷”注入不同颜色的水,不断的注水,水位则不断上升,注入的水将灌满山谷,并可能淹没山峰,为了防止不同颜色的山谷中的水溢出汇合,我们可在汇合的地方筑起堤坝,故可将堤坝看作是对图像的分割后形成的边界。 而常规的分水岭算法由于图像上噪声和图局部不连续原因常常表现出过度分割。由于噪声的存在以及连接物体的特点,传统的标记分水岭算法对包含连接物体的灰度图像很难取得满意的分割结果;特别是在背景并不连通的情况下,误分割更为常见。为此,在标记分水岭算法的基础上,提出了一种连接物体分割方法;将属于鲁棒统计的Hough变换(也就是统计霍夫变换)用于提取物体标记扩展了标记分水岭算法的应用范围;针对在分割连接物体时,由于背景并非连通,因此允许背景被分别标记,并通过一个后续滤波步骤用以剔除分割后图像中的背景部分,从而得到精确的分割图像;试验证明该算法运算速度快,鲁棒性好,具有广泛的应用价值。感兴趣的读者可以去查阅一些相关的资料。 本文到此结束,谢谢大家。