Opencv学习笔记(二十一)分水岭算法

文章目录

分水岭算法

假设一副灰度图像看作是地势图,灰度值高的区域可以被看成是
山峰,灰度值低的区域可以被看成是山谷。开始向山谷中注入水,随着水位的升高,不同的山谷中的水将要汇聚,为了防止不同山谷的水汇合,我们需要在水汇合的区域构建堤坝。不停的灌水,不停的构建堤坝直至所有的山峰都被水淹没。我们构建好的堤坝就是对图像的分割。

代码

# 分水岭算法
import cv2
import numpy as np
from matplotlib import pyplot as plt
src = cv2.imread(r'F:\OPENCV\Opencv\coin.png')
if src is None:
    print('image is empty')
img = src.copy()
img = cv2.medianBlur(img, 5)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 阈值化
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)
# 形态学操作, 去除噪声
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 膨胀, 获取背景
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 距离变换
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret2, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# 获取未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)  # 不确定区域
# cv2.connectedComponents()将前景从1开始的正整数标记,背景标为0, 未知区域为-1
ret3, markers = cv2.connectedComponents(sure_fg)  # 标签化
markers = markers + 1  # 所有标签+1, 目的是将背景标签从0变为1, 因为标签为0会被算法识别为背景区域
markers[unknown == 255] = 0  # 未知区域标记为0
# cv2.watershed() 开始注水
markers2 = cv2.watershed(img, markers)

img[markers2 == -1] = [0, 0, 255]
img[markers2 >= 1] = [255, 255, 255]
# 显示结果
titles = ['src', 'gray', 'sure_bg', 'dist_transform', 'sure_fg', 'unknown', "result"]
images = [src[:, :, ::-1], gray, sure_bg, dist_transform, sure_fg, unknown, img[:, :, ::-1]]
plt.figure(1)
for i in range(len(images)):
    plt.subplot(3, 3, i + 1)
    plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.subplot(3, 3, 9)
plt.imshow(np.abs(markers), 'jet')
plt.title('markers')
plt.xticks([])
plt.yticks([])
plt.show()

结果显示
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值