python数字图像处理之骨架提取与分水岭算法


Posted in Python onApril 27, 2018

骨架提取与分水岭算法也属于形态学处理范畴,都放在morphology子模块内。

1、骨架提取

骨架提取,也叫二值图像细化。这种算法能将一个连通区域细化成一个像素的宽度,用于特征提取和目标拓扑表示。

morphology子模块提供了两个函数用于骨架提取,分别是Skeletonize()函数和medial_axis()函数。我们先来看Skeletonize()函数。

格式为:skimage.morphology.skeletonize(image)

输入和输出都是一幅二值图像。

例1:

from skimage import morphology,draw
import numpy as np
import matplotlib.pyplot as plt

#创建一个二值图像用于测试
image = np.zeros((400, 400))

#生成目标对象1(白色U型)
image[10:-10, 10:100] = 1
image[-100:-10, 10:-10] = 1
image[10:-10, -100:-10] = 1

#生成目标对象2(X型)
rs, cs = draw.line(250, 150, 10, 280)
for i in range(10):
 image[rs + i, cs] = 1
rs, cs = draw.line(10, 150, 250, 280)
for i in range(20):
 image[rs + i, cs] = 1

#生成目标对象3(O型)
ir, ic = np.indices(image.shape)
circle1 = (ic - 135)**2 + (ir - 150)**2 < 30**2
circle2 = (ic - 135)**2 + (ir - 150)**2 < 20**2
image[circle1] = 1
image[circle2] = 0

#实施骨架算法
skeleton =morphology.skeletonize(image)

#显示结果
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))

ax1.imshow(image, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('original', fontsize=20)

ax2.imshow(skeleton, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title('skeleton', fontsize=20)

fig.tight_layout()
plt.show()

生成一幅测试图像,上面有三个目标对象,分别进行骨架提取,结果如下:

python数字图像处理之骨架提取与分水岭算法

例2:利用系统自带的马图片进行骨架提取

from skimage import morphology,data,color
import matplotlib.pyplot as plt

image=color.rgb2gray(data.horse())
image=1-image #反相
#实施骨架算法
skeleton =morphology.skeletonize(image)

#显示结果
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(8, 4))

ax1.imshow(image, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('original', fontsize=20)

ax2.imshow(skeleton, cmap=plt.cm.gray)
ax2.axis('off')
ax2.set_title('skeleton', fontsize=20)

fig.tight_layout()
plt.show()

python数字图像处理之骨架提取与分水岭算法

medial_axis就是中轴的意思,利用中轴变换方法计算前景(1值)目标对象的宽度,格式为:

skimage.morphology.medial_axis(image,mask=None,return_distance=False)

mask: 掩模。默认为None, 如果给定一个掩模,则在掩模内的像素值才执行骨架算法。

return_distance: bool型值,默认为False. 如果为True, 则除了返回骨架,还将距离变换值也同时返回。这里的距离指的是中轴线上的所有点与背景点的距离。

import numpy as np
import scipy.ndimage as ndi
from skimage import morphology
import matplotlib.pyplot as plt

#编写一个函数,生成测试图像
def microstructure(l=256):
 n = 5
 x, y = np.ogrid[0:l, 0:l]
 mask = np.zeros((l, l))
 generator = np.random.RandomState(1)
 points = l * generator.rand(2, n**2)
 mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1
 mask = ndi.gaussian_filter(mask, sigma=l/(4.*n))
 return mask > mask.mean()

data = microstructure(l=64) #生成测试图像

#计算中轴和距离变换值
skel, distance =morphology.medial_axis(data, return_distance=True)

#中轴上的点到背景像素点的距离
dist_on_skel = distance * skel

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.imshow(data, cmap=plt.cm.gray, interpolation='nearest')
#用光谱色显示中轴
ax2.imshow(dist_on_skel, cmap=plt.cm.spectral, interpolation='nearest')
ax2.contour(data, [0.5], colors='w') #显示轮廓线

fig.tight_layout()
plt.show()

python数字图像处理之骨架提取与分水岭算法

2、分水岭算法

分水岭在地理学上就是指一个山脊,水通常会沿着山脊的两边流向不同的“汇水盆”。分水岭算法是一种用于图像分割的经典算法,是基于拓扑理论的数学形态学的分割方法。如果图像中的目标物体是连在一起的,则分割起来会更困难,分水岭算法经常用于处理这类问题,通常会取得比较好的效果。

分水岭算法可以和距离变换结合,寻找“汇水盆地”和“分水岭界限”,从而对图像进行分割。二值图像的距离变换就是每一个像素点到最近非零值像素点的距离,我们可以使用scipy包来计算距离变换。

在下面的例子中,需要将两个重叠的圆分开。我们先计算圆上的这些白色像素点到黑色背景像素点的距离变换,选出距离变换中的最大值作为初始标记点(如果是反色的话,则是取最小值),从这些标记点开始的两个汇水盆越集越大,最后相交于分山岭。从分山岭处断开,我们就得到了两个分离的圆。

例1:基于距离变换的分山岭图像分割

import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage as ndi
from skimage import morphology,feature

#创建两个带有重叠圆的图像
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)

#现在我们用分水岭算法分离两个圆
distance = ndi.distance_transform_edt(image) #距离变换
local_maxi =feature.peak_local_max(distance, indices=False, footprint=np.ones((3, 3)),
       labels=image) #寻找峰值
markers = ndi.label(local_maxi)[0] #初始标记点
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.spectral, interpolation='nearest')
ax2.set_title("Markers")
ax3.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest')
ax3.set_title("Segmented")

for ax in axes:
 ax.axis('off')

fig.tight_layout()
plt.show()

python数字图像处理之骨架提取与分水岭算法

分水岭算法也可以和梯度相结合,来实现图像分割。一般梯度图像在边缘处有较高的像素值,而在其它地方则有较低的像素值,理想情况 下,分山岭恰好在边缘。因此,我们可以根据梯度来寻找分山岭。

例2:基于梯度的分水岭图像分割

import matplotlib.pyplot as plt
from scipy import ndimage as ndi
from skimage import morphology,color,data,filter

image =color.rgb2gray(data.camera())
denoised = filter.rank.median(image, morphology.disk(2)) #过滤噪声

#将梯度值低于10的作为开始标记点
markers = filter.rank.gradient(denoised, morphology.disk(5)) <10
markers = ndi.label(markers)[0]

gradient = filter.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.spectral, interpolation='nearest')
ax1.set_title("Gradient")
ax2.imshow(markers, cmap=plt.cm.spectral, interpolation='nearest')
ax2.set_title("Markers")
ax3.imshow(labels, cmap=plt.cm.spectral, interpolation='nearest')
ax3.set_title("Segmented")

for ax in axes:
 ax.axis('off')

fig.tight_layout()
plt.show()

python数字图像处理之骨架提取与分水岭算法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中暂存上传图片的方法
Feb 18 Python
Python 爬虫多线程详解及实例代码
Oct 08 Python
浅谈Django学习migrate和makemigrations的差别
Jan 18 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
Jan 15 Python
关于python多重赋值的小问题
Apr 17 Python
用Python实现最速下降法求极值的方法
Jul 10 Python
使用python实现希尔、计数、基数基础排序的代码
Dec 25 Python
Keras 实现加载预训练模型并冻结网络的层
Jun 15 Python
Python爬虫之Selenium库的使用方法
Jan 03 Python
python 获取谷歌浏览器保存的密码
Jan 06 Python
如何用Python和JS实现的Web SSH工具
Feb 23 Python
Python socket如何解析HTTP请求内容
Feb 12 Python
python多线程之事件Event的使用详解
Apr 27 #Python
python线程池threadpool使用篇
Apr 27 #Python
Python实现删除时保留特定文件夹和文件的示例
Apr 27 #Python
python中yaml配置文件模块的使用详解
Apr 27 #Python
python 拷贝特定后缀名文件,并保留原始目录结构的实例
Apr 27 #Python
python中subprocess批量执行linux命令
Apr 27 #Python
python复制文件到指定目录的实例
Apr 27 #Python
You might like
Amazon Prime Video平台《无限住人 -IMMORTAL-》2020年开始TV放送!
2020/03/06 日漫
Laravel 5框架学习之表单
2015/04/08 PHP
PHP单例模式详细介绍
2015/07/01 PHP
Thinkphp批量更新数据的方法汇总
2016/06/29 PHP
JavaScript实用技巧(一)
2010/08/16 Javascript
Jquery下EasyUI组件中的DataGrid结果集清空方法
2014/01/06 Javascript
jQuery学习笔记之toArray()
2014/06/09 Javascript
快速解决Canvas.toDataURL 图片跨域的问题
2016/05/10 Javascript
JavaScript实现复制或剪切内容到剪贴板功能的方法
2016/05/23 Javascript
基于HTML5+JS实现本地图片裁剪并上传功能
2017/03/24 Javascript
Vue.js实现实例搜索应用功能详细代码
2017/08/24 Javascript
nodejs实现解析xml字符串为对象的方法示例
2018/03/14 NodeJs
layer.confirm取消按钮绑定事件的方法
2018/08/17 Javascript
Vue框架里使用Swiper的方法示例
2018/09/20 Javascript
简单了解JavaScript sort方法
2019/11/25 Javascript
Vue实现base64编码图片间的切换功能
2019/12/04 Javascript
如何优雅地取消 JavaScript 异步任务
2020/03/22 Javascript
jQuery加PHP实现图片上传并提交的示例代码
2020/07/16 jQuery
[04:44]DOTA2西游记战队视频彩蛋流出 师徒开黑巧遇林书豪
2016/08/03 DOTA
Python两个整数相除得到浮点数值的方法
2015/03/18 Python
Python编程判断这天是这一年第几天的方法示例
2017/04/18 Python
eDreams澳大利亚:预订机票、酒店和度假产品
2017/04/19 全球购物
伦敦一卡通:The London Pass
2018/11/30 全球购物
C语言编程练习
2012/04/02 面试题
农田水利实习自我鉴定
2013/09/19 职场文书
法律专业实习鉴定
2013/12/22 职场文书
便利店的创业计划书
2014/01/15 职场文书
闭幕式主持词
2014/04/02 职场文书
竞选班干部的演讲稿
2014/04/24 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
业务员年终工作总结2015
2015/05/28 职场文书
小学教育见习总结
2015/06/23 职场文书
新闻通讯稿范文
2015/07/22 职场文书
学习焦裕禄先进事迹心得体会
2016/01/23 职场文书
pytorch finetuning 自己的图片进行训练操作
2021/06/05 Python
关于Oracle12C默认用户名system密码不正确的解决方案
2021/10/16 Oracle