分水岭算法(Watershed Algorithm),是根据分水岭的构成来考虑图像的分割。现实中我们可以或者说可以想象有山有湖的景象,那么那一定是水绕山,山围水的情形。当然在需要的时候,要人工构筑分水岭,以防集水盆之间的互相穿透。而区分高山(plateaus)与水的界线,以及湖与湖之间的间隔或 都是连通的关系,就是分水岭(watershed)。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 读取图片
print("--------- Python OpenCV Tutorial ---------")
src = cv.imread("1.jpg")
plt.imshow(src)
# 滤波/模糊处理
# 高斯模糊
blur_Gaussian = cv.GaussianBlur(src,(5,5),0)
plt.imshow(blur_Gaussian[:,:,::-1])
进行二值化之前先进行灰度化
# gray\binary image
gray = cv.cvtColor(blur_Gaussian, cv.COLOR_BGR2GRAY) # 改变图像的颜色空间,灰度化
plt.imshow(gray,cmap=plt.cm.gray)
# Otsu阈值
ret_ostu,ostu = cv.threshold(gray,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
plt.imshow(ostu,cmap=plt.cm.gray)
# 开操作
# morphology operation 去除小的干扰块 进行开操作和膨胀操作
kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) # 函数构建并返回一个结构元素,MORPH_RECT方形
mor_open = cv.morphologyEx(ostu, cv.MORPH_OPEN, kernel, iterations=2) # 开运算是通过先对图像腐蚀再膨胀实现的。
plt.imshow(mor_open,cmap=plt.cm.gray)
# 确定背景区域
sure_bg = cv.dilate(mor_open_4, kernel, iterations=3) # 对输入图像用特定结构元素进行膨胀操作
plt.imshow(sure_bg ,cmap=plt.cm.gray)
# 寻找前景区域
dist_transform = cv.distanceTransform(mor_open ,cv.DIST_L2,5)
ret, sure_fg = cv.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# 找到未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg,sure_fg)
# 类别标记
ret, markers = cv.connectedComponents(sure_fg)
# 为所有的标记加1,保证背景是0而不是1
markers = markers+1
# 现在让所有的未知区域为0
markers[unknown==255] = 0
现在是最后一步的时候了,使用分水岭算法。然后标记图像将被修改。边界区域将标记为-1。
# 分水岭算法
markers = cv.watershed(src, markers=markers)
src[markers==-1] = [0, 0, 255]
plt.imshow(src[:,:,::-1])
文档:http://www.woshicver.com/FifthSection/4_15_%E5%9B%BE%E5%83%8F%E5%88%86%E5%89%B2%E4%B8%8E%E5%88%86%E6%B0%B4%E5%B2%AD%E7%AE%97%E6%B3%95/