侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   236

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

1、骨架提取

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

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

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

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

例1:

from skimage import morphology,drawimport numpy as npimport matplotlib.pyplot as plt#创建一个二值图像用于测试image = np.zeros((400, 400))#生成目标对象1(白色U型)image[10:-10, 10:100] = 1image[-100:-10, 10:-10] = 1image[10:-10, -100:-10] = 1#生成目标对象2(X型)rs, cs = draw.line(250, 150, 10, 280)for i in range(10): image[rs + i, cs] = 1rs, 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**2circle2 = (ic - 135)**2 + (ir - 150)**2 < 20**2image[circle1] = 1image[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()

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

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

from skimage import morphology,data,colorimport matplotlib.pyplot as pltimage=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()

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

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

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

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

import numpy as npimport scipy.ndimage as ndifrom skimage import morphologyimport 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 * skelfig, (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()

2、分水岭算法

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

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

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

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

import numpy as npimport matplotlib.pyplot as pltfrom scipy import ndimage as ndifrom skimage import morphology,feature#创建两个带有重叠圆的图像x, y = np.indices((80, 80))x1, y1, x2, y2 = 28, 28, 44, 52r1, r2 = 16, 20mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2image = 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 = axesax0.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()

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

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

import matplotlib.pyplot as pltfrom scipy import ndimage as ndifrom skimage import morphology,color,data,filterimage =color.rgb2gray(data.camera())denoised = filter.rank.median(image, morphology.disk(2)) #过滤噪声#将梯度值低于10的作为开始标记点markers = filter.rank.gradient(denoised, morphology.disk(5)) <10markers = 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 = axesax0.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线程池threadpool实现篇
    下一条:
    python多线程之事件Event的使用详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客