基于距离的分水岭分割流程:
1、输入图像
2、灰度(消除噪声)
3、二值化
4、距离变换
5、寻找种子
6、生成Marker
7、分水岭变换
8、输出图像
原理参考:分水岭分割原理
from cv2 import cv2 as cv
import numpy as np
def watearshel_demo():
print(img.shape)
# # 进行mean shift滤波 去噪
blured = cv.pyrMeanShiftFiltering(img, 10, 80)
# 操作步骤 gray/binary image
gray = cv.cvtColor(blured, cv.COLOR_BGR2GRAY) # 观察灰度处理后的图像好不好,不好就进行滤波
# 图像二值化 进行阈值分割
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("binary_image", binary)
# morphology operation 形态学操作
kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 1)) # 结构元素
mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2) # 进行2次开操作
sure_bg = cv.dilate(mb, kernel, iterations=3) # 进行3次膨胀
cv.imshow("mor", sure_bg)
# distace transform
# 对mb进行距离变换
dist = cv.distanceTransform(mb, cv.DIST_L2, 3)
# 归一化处理
dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)
cv.imshow("distanc_transform", dist_output * 50)
ret, surface = cv.threshold(dist, dist.max() * 0.6, 255, cv.THRESH_BINARY)
cv.imshow("surface", surface)
# 种子surface_fg
surface_fg = np.uint8(surface) # 转成int
# 其他的未知区域
unknow = cv.subtract(sure_bg, surface_fg)
# 联通区域 它会把将背景标记为 0,其他的对象使用从 1 开始的正整数标记。
ret, markers = cv.connectedComponents(surface_fg)
print(ret)
# watershed transform
# 确保背景是1不是0
markers = markers + 1
# 未知区域标记为0
markers[unknow == 255] = 0
# 分水岭 结果:标签图像将会被修改,边界区域的标记将变为 -1
markers = cv.watershed(img, markers=markers)
# 获得到的边界值为-1
img[markers == -1] = [0, 0, 255] # 红色
cv.imshow('result', img)
if __name__ == "__main__":
img = cv.imread("data/coins.jpg") # blue green red
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", img)
watearshel_demo()
cv.waitKey(0)
cv.destroyAllWindows()