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数据结构之Array用法实例
Oct 09 Python
Linux下用Python脚本监控目录变化代码分享
May 21 Python
Python实现的递归神经网络简单示例
Aug 11 Python
python3大文件解压和基本操作
Dec 15 Python
Caffe均值文件mean.binaryproto转mean.npy的方法
Jul 09 Python
Windows下python3.6.4安装教程
Jul 31 Python
tensorflow 模型权重导出实例
Jan 24 Python
Python selenium环境搭建实现过程解析
Sep 08 Python
django如何自定义manage.py管理命令
Apr 27 Python
Pytorch使用shuffle打乱数据的操作
May 20 Python
Python趣味挑战之实现简易版音乐播放器
May 28 Python
详解Python函数print用法
Jun 18 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
PHP 转义使用详解
2013/07/15 PHP
ThinkPHP中使用ajax接收json数据的方法
2014/12/18 PHP
微信公众平台开发关注及取消关注事件的方法
2014/12/23 PHP
PHP中使用Imagick实现各种图片效果实例
2015/01/21 PHP
php中return的用法实例分析
2015/02/28 PHP
在html文件中也可以执行php语句的方法
2015/04/09 PHP
php获取系统变量方法小结
2015/05/29 PHP
PHP实现无限级分类(不使用递归)
2015/10/22 PHP
addRule在firefox下的兼容写法
2006/11/30 Javascript
Jquery 改变radio/checkbox选中状态,获取选中的值(示例代码)
2013/12/12 Javascript
jquery列表拖动排列(由项目提取相当好用)
2014/06/17 Javascript
new Date()问题在ie8下面的处理方法
2014/07/31 Javascript
jquery.qtip提示信息插件用法简单实例
2016/06/17 Javascript
浅谈jquery的html方法里包含特殊字符的处理
2016/11/30 Javascript
详解用webpack2.0构建vue2.0超详细精简版
2017/04/05 Javascript
javascript 的变量、作用域和内存问题
2017/04/19 Javascript
小程序云开发如何实现图片上传及发表文字
2019/05/17 Javascript
node.js中事件触发器events的使用方法实例分析
2019/11/23 Javascript
[47:55]Ti4第二日主赛事败者组 NaVi vs EG 1
2014/07/20 DOTA
[45:18]完美世界DOTA2联赛循环赛 PXG vs IO 第二场 11.06
2020/11/09 DOTA
Python 内置函数memoryview(obj)的具体用法
2017/11/23 Python
在python中bool函数的取值方法
2018/11/01 Python
对python mayavi三维绘图的实现详解
2019/01/08 Python
Python多线程同步---文件读写控制方法
2019/02/12 Python
利用python Selenium实现自动登陆京东签到领金币功能
2019/10/31 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
2020/01/03 Python
Django form表单与请求的生命周期步骤详解
2020/06/07 Python
基于HTML5实现类似微信手机摇一摇功能(计算摇动次数)
2017/07/24 HTML / CSS
意大利综合购物网站:Giordano Shop
2016/10/21 全球购物
Currentbody法国:健康与美容高科技产品
2020/08/16 全球购物
几个常见的消息中间件(MOM)
2014/01/08 面试题
优乐美广告词
2014/03/14 职场文书
党员政治学习材料
2014/05/14 职场文书
爱护公共设施的标语
2014/06/24 职场文书
民主评议党员工作总结
2014/10/20 职场文书
学校三八妇女节活动总结
2015/02/06 职场文书