import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage as ndi
from skimage import morphology, feature, color, data, filters
#-----------------------------------------------------------#
# 基于距离变换的分水岭分割
# 特适用两个目标连载一块 / 将其分开的情形
#-----------------------------------------------------------#
def distance_water(image_path):
#-------------------------------------------------------#
# 读入图像 / 二值化 / 显示图像
#-------------------------------------------------------#
# image = cv2.imread(image_path)
# image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# ret, image = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY_INV)
# # ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# cv2.namedWindow('image', 0)
# cv2.imshow('image', image)
# cv2.waitKey(0)
#-------------------------------------------------------#
# 想要更明显的看出效果使用下面的自己创建的两个挨在一起的圆
# 创建两个带有重叠圆的图像
#-------------------------------------------------------#
x, y = np.indices((80, 80))
x1, y1, x2, y2 = 28, 28, 44, 52
r1, r2 = 16, 20
mask_circle1 = (x - x1) ** 2 + (y - y1) ** 2 < r1 ** 2
mask_circle2 = (x - x2) ** 2 + (y - y2) ** 2 < r2 ** 2
image = np.logical_or(mask_circle1, mask_circle2)
#-------------------------------------------------------#
# scipy 距离变化 / distance_transform_edt
# 计算图像中非零点到最近背景点(即0)的距离
# peak_local_max函数返回图像中局部峰值的坐标
#-------------------------------------------------------#
distance = ndi.distance_transform_edt(image)
# print(distance[40:80, 40:80])
# print(distance[distance == 20].sum())
#-------------------------------------------------------#
# peak_local_max返回和图像相同形状的数组,
# 对其中的峰值点进行标记为True / 其余False
#-------------------------------------------------------#
local_maxi = feature.peak_local_max(distance,
indices=False,
footprint=np.ones((3, 3)),
labels=image) # 寻找峰值
#-------------------------------------------------------#
# ndi.label 返回 列表 / 峰值个数
markers = ndi.label(local_maxi)[0] # 初始标记点
# print(ndi.label(local_maxi)[0])
#-------------------------------------------------------#
# 基于距离变换的分水岭算法
# 1. 以原始图像的前景区域为边界进行填充,
# 2. 输入地势条件-distance,数值越低表示地势越低,
# 3. markers为注水点标记,
# 4. 注水时会以注水点标记为数值,以相应的类别值为水值进行注水。
#-------------------------------------------------------#
labels = morphology.watershed(-distance, markers, mask=image)
#-------------------------------------------------------#
# 画图 / 显示
#-------------------------------------------------------#
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(8, 8))
# 拉伸成一维数组
axes = axes.ravel()
ax0, ax1, ax2, ax3 = axes
ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
ax0.set_title("Original")
ax1.imshow(-distance, cmap=plt.cm.jet, interpolation='nearest')
ax1.set_title("Distance")
ax2.imshow(markers, cmap=plt.cm.winter, interpolation='nearest')
ax2.set_title("Markers")
ax3.imshow(labels, cmap=plt.cm.winter, interpolation='nearest')
ax3.set_title("Segmented")
for ax in axes:
ax.axis('off')
fig.tight_layout()
plt.savefig('./image/distance_water.png')
plt.show()
#-----------------------------------------------------------#
# 基于梯度的分水岭分割
# 使用于边缘较为明显,差异交大的图像分割
# 原理:1. 梯度图像在边缘处有较高的像素值,在其它地方则有较低的像素值,
# 2. 理想情况下,分山岭恰好在边缘,因此可以根据梯度来寻找分山岭。
#-----------------------------------------------------------#
def gradient_water(image_path):
# image = cv2.imread(image_path)
# image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# ret, image = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY_INV)
# ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# cv2.namedWindow('image', 0)
# cv2.imshow('image', image)
# cv2.waitKey(0)
#-------------------------------------------------------#
# 1."data/camera.png"
# 2. 过滤噪声 / morphology.disk()滤波器
# 3. 中值滤波
image = color.rgb2gray(data.camera())
denoised = filters.rank.median(image, morphology.disk(2))
# 将梯度值低于10的作为开始标记点
markers = filters.rank.gradient(denoised, morphology.disk(5)) < 10
markers = ndi.label(markers)[0]
# 计算梯度
gradient = filters.rank.gradient(denoised, morphology.disk(2))
# 基于梯度的分水岭算法
labels = morphology.watershed(gradient, markers, mask=image)
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(6, 6))
axes = axes.ravel()
ax0, ax1, ax2, ax3 = axes
ax0.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
ax0.set_title("Original")
ax1.imshow(gradient, cmap=plt.cm.winter, interpolation='nearest')
ax1.set_title("Gradient")
ax2.imshow(markers, cmap=plt.cm.jet, interpolation='nearest')
ax2.set_title("Markers")
ax3.imshow(labels, cmap=plt.cm.jet, interpolation='nearest')
ax3.set_title("Segmented")
for ax in axes:
ax.axis('off')
fig.tight_layout()
plt.savefig('./image/gradient_water.png')
plt.show()
if __name__ == "__main__":
image_path = './image/1.JPG'
# distance_water(image_path)
gradient_water(image_path)
没有合适的资源?快使用搜索试试~ 我知道了~
传统的图像分割方法包含代码/注释/结果
共17个文件
png:5个
py:4个
xml:4个
5星 · 超过95%的资源 需积分: 17 6 下载量 76 浏览量
2022-04-20
21:26:00
上传
评论 2
收藏 2.98MB ZIP 举报
温馨提示
1.分水岭 2.kemeans 3.gmm 4.grabcut
资源详情
资源评论
资源推荐
收起资源包目录
traditional segmentation.zip (17个子文件)
traditional segmentation
grabcut.py 1KB
image
lun.jpg 36KB
0.png 201KB
1.JPG 1.99MB
li.jpg 39KB
gmm.py 1KB
result
gmm.png 329KB
kmeans.png 228KB
gradient_water.png 166KB
distance_water.png 19KB
.idea
misc.xml 201B
traditional segmentation.iml 595B
modules.xml 307B
workspace.xml 6KB
inspectionProfiles
profiles_settings.xml 174B
kmeans.py 3KB
watershed.py 6KB
共 17 条
- 1
Charms@
- 粉丝: 736
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论1