Zhang-Suen细化算法提取中轴线(Python)
骨架
表示一个平面区域的结构形状的一种重要方法是将它简化为图形,这种简化可以通过一种细化(也称为骨架化)算法得到该区域的骨架来实现。细化是一种形态学变形,在提取中轴线的图像处理问题中,细化起着核心作用。为了产生一个区域的中轴的表示,提出了许多典型的算法,这些算法都是通过迭代一个区域的边界点的细化过程,删除这些点时需要服从如下约束条件:(1)不能删除端点,(2)不能破坏连接性,(3)不能导致区域的过度腐蚀。
因此,细化算法的一次迭代由如下步骤组成:(1)标记将被删除的边界点;(2)删除做了标记的点;(3)继续标记将被删除的剩余的边界点;(4)删除标记过的点。反复应用这个基本过程,直到再也没有被删除的点为止,此时算法终止,生成了该区域的骨架。
Zhang-Suen细化算法
首先定义像素点的8邻域如下图(前景为1,背景为0):
# 定义像素点周围的8邻域
# P9 P2 P3
# P8 P1 P4
# P7 P6 P5def neighbours(x,y,image):img = imagex_1, y_1, x1, y1 = x-1, y-1, x+1, y+1return [ img[x_1][y],img[x_1][y1],img[x][y1],img[x1][y1], # P2,P3,P4,P5img[x1][y], img[x1][y_1], img[x][y_1], img[x_1][y_1] ] # P6,P7,P8,P9
N(p1)表示与1相邻的8个像素点中,为前景像素点的个数。
for x in range(1, rows - 1):for y in range(1, columns - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, Image_Thinned)
S(P1)表示从P2 ~ P9中出现0~1的累计次数,其中0表示背景,1表示前景。
# 计算邻域像素从0变化到1的次数def transitions(neighbours):n = neighbours + neighbours[0:1] # P2,P3,...,P8,P9,P2return sum( (n1, n2) == (0, 1) for n1, n2 in zip(n, n[1:]) ) # (P2,P3),(P3,P4),...,(P8,P9),(P9,P2)
Zhang-Suen细化算法的整个迭代过程分为两步:
Step One:循环所有前景像素点,对符合如下条件的像素点标记为删除:
1. 2 <= N(p1) <=6,中心像素p1周围的目标像素(二值中的1)的个数在2~6之间;
2. S(P1) = 1,8邻域像素中,按顺时针方向,相邻两个像素出现0→1的次数;
3. P2 * P4 * P6 = 0
4. P4 * P6 * P8 = 0
# Step 1
changing1 = []
rows, columns = Image_Thinned.shape
for x in range(1, rows - 1):for y in range(1, columns - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, Image_Thinned)if (Image_Thinned[x][y] == 1 and # Condition 0: Point P1 in the object regions 2 <= sum(n) <= 6 and # Condition 1: 2<= N(P1) <= 6transitions(n) == 1 and # Condition 2: S(P1)=1 P2 * P4 * P6 == 0 and # Condition 3 P4 * P6 * P8 == 0): # Condition 4
Step Two:跟Step One很类似,条件1、2完全一致,只是条件3、4稍微不同,满足如下条件的像素P1则标记为删除,条件如下:
1. 2 <= N(p1) <=6
2. S(P1) = 1
3. P2 * P4 * P8 = 0
4. P2 * P6 * P8 = 0
循环上述两步骤,直到两步中都没有像素被标记为删除为止,输出的结果即为二值图像细化后的骨架。
# Step 2
changing2 = []
for x in range(1, rows - 1):for y in range(1, columns - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, Image_Thinned)if (Image_Thinned[x][y] == 1 and # Condition 02 <= sum(n) <= 6 and # Condition 1transitions(n) == 1 and # Condition 2P2 * P4 * P8 == 0 and # Condition 3P2 * P6 * P8 == 0): # Condition 4changing2.append((x,y))
for x, y in changing2: Image_Thinned[x][y] = 0
伪代码
算法完整代码
# 导入库
import matplotlib
import matplotlib.pyplot as plt
import skimage.io as io# 将图像转为灰度图像
from PIL import Image
img = Image.open("E://straight//3.png").convert('L')
img.save('E://straight//3 greyscale.png')# 读取灰度图像
Img_Original = io.imread('E://straight//3 greyscale.png')# 对图像进行预处理,二值化
from skimage import filters
from skimage.morphology import disk
# 中值滤波
Img_Original = filters.median(Img_Original,disk(5))
# 二值化
BW_Original = Img_Original < 235
# 定义像素点周围的8邻域
# P9 P2 P3
# P8 P1 P4
# P7 P6 P5def neighbours(x,y,image):img = imagex_1, y_1, x1, y1 = x-1, y-1, x+1, y+1return [ img[x_1][y],img[x_1][y1],img[x][y1],img[x1][y1], # P2,P3,P4,P5img[x1][y], img[x1][y_1], img[x][y_1], img[x_1][y_1] ] # P6,P7,P8,P9# 计算邻域像素从0变化到1的次数
def transitions(neighbours):n = neighbours + neighbours[0:1] # P2,P3,...,P8,P9,P2return sum( (n1, n2) == (0, 1) for n1, n2 in zip(n, n[1:]) ) # (P2,P3),(P3,P4),...,(P8,P9),(P9,P2)# Zhang-Suen 细化算法
def zhangSuen(image):Image_Thinned = image.copy() # Making copy to protect original imagechanging1 = changing2 = 1while changing1 or changing2: # Iterates until no further changes occur in the image# Step 1changing1 = []rows, columns = Image_Thinned.shapefor x in range(1, rows - 1):for y in range(1, columns - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, Image_Thinned)if (Image_Thinned[x][y] == 1 and # Condition 0: Point P1 in the object regions 2 <= sum(n) <= 6 and # Condition 1: 2<= N(P1) <= 6transitions(n) == 1 and # Condition 2: S(P1)=1 P2 * P4 * P6 == 0 and # Condition 3 P4 * P6 * P8 == 0): # Condition 4changing1.append((x,y))for x, y in changing1: Image_Thinned[x][y] = 0# Step 2changing2 = []for x in range(1, rows - 1):for y in range(1, columns - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, Image_Thinned)if (Image_Thinned[x][y] == 1 and # Condition 02 <= sum(n) <= 6 and # Condition 1transitions(n) == 1 and # Condition 2P2 * P4 * P8 == 0 and # Condition 3P2 * P6 * P8 == 0): # Condition 4changing2.append((x,y)) for x, y in changing2: Image_Thinned[x][y] = 0return Image_Thinned
# 对染色体图像应用Zhang-Suen细化算法
BW_Skeleton = zhangSuen(BW_Original)
import numpy as np
BW_Skeleton = np.invert(BW_Skeleton)
# 显示细化结果
fig, ax = plt.subplots(1, 2)
ax1, ax2 = ax.ravel()
ax1.imshow(img, cmap=plt.cm.gray)
ax1.set_title('Original binary image')
ax1.axis('off')
ax2.imshow(BW_Skeleton, cmap=plt.cm.gray)
ax2.set_title('Skeleton of the image')
ax2.axis('off')
plt.savefig('E://straight//3 thinned.png')
plt.show()
# 生成骨架图像并保存
Skeleton = np.ones((BW_Skeleton.shape[0],BW_Skeleton.shape[1]),np.uint8) *255 #生成一个空灰度图像
BW_Skeleton = BW_Skeleton + 0
for i in range(BW_Skeleton.shape[0]):for j in range(BW_Skeleton.shape[1]):if BW_Skeleton[i][j] == 0:Skeleton[i][j] = 0plt.axis('off')
plt.imshow(Skeleton, cmap=plt.cm.gray)import imageio
imageio.imwrite('E://straight//3 Skeleton.png', Skeleton)
# 利用opencv在染色体图像上画出中轴线
import numpy as np
import cv2 as cvimg = cv.imread('E://straight//3 Skeleton.png')
binaryImg = cv.Canny(img,100,200)
h = cv.findContours(binaryImg, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
contours = h[1]Org_img = cv.imread('E://straight//3.png')
cv.drawContours(Org_img, contours, -1,(0,0,255),3)plt.axis('off')
plt.imshow(Org_img, cmap=plt.cm.gray)cv.imwrite('E://straight//3 contours.png',Org_img)
Zhang-Suen细化算法提取中轴线(Python)相关推荐
- 改进Zhang Suen细化算法的C#实现
本文主要实现了改进Zhang Suen细化算法的C#实现,相关论文 :"牟少敏,杜海洋,苏平,查绪恒,陈光艺.一种改进的快速并行细化算法[J].微电子学与计算机,2013,(第1期)&quo ...
- C#:实现Zhang Suen细化算法(附完整源码)
C#:实现Zhang Suen细化算法 #region xqpublic Bitmap zhang_thinimage_improve(Bitmap bmp){int imgWidth = bmp.W ...
- 图像处理之Zhang Suen细化算法
在二值图像处理特别是OCR识别与匹配中,都要通过对字符进行细化以便获得图像的骨架,通过zhang-suen细化算法获得图像,作为图像的特征之一,常用来作为识别或者模式匹配. 一:算法介绍 Zhang- ...
- zhang 快速并行细化方法_一种改进的Zhang并行图像细化算法的制作方法
本发明涉及图像处理技术,具体涉及一种改进的Zhang并行图像细化算法. 背景技术: 图像细化是将图像的线条从多像素宽度减少到单位像素宽度,简称骨架化.细化效果的好坏直接影响后期图像处理的效果.对于二值 ...
- python图像线条提取_python3 图像细化(提取骨架线)
图像细化_八连通法 图像细化 图像细化的方法 八连通-查表法 zhang的快速并行细化算法 八连通-查表法的改进 附上参考链接:https://www.cnblogs.com/xianglan/arc ...
- python图像算法,Zhang-Suen 图像细化算法python实现
算法流程 首先要反转原图像,因为算法之后所有的操作都将0作为前景,将1作为背景. 中心像素x_1(x,y)的8-近邻定义如下所示: 考虑以下两个步骤 步骤1:执行光栅扫描并标记满足以下5个条件的所有像 ...
- 手指静脉细化算法过程原理解析 以及python实现细化算法
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8672489.html 文中的一些图片以及思想很多都是参考https://www.cnblogs ...
- 3D骨架(细化)提取算法C++
网上的细化算法大部分都是对2D图像进行提取,对3D图像进行细化代码介绍太少了.目前比较流行的有两个版本. matlat版本 Skeleton3D. ITK版本 itkBinaryThinningIma ...
- OpenCV python GrabCut算法提取前景背景图片
OpenCV python GrabCut算法提取前景背景图片 处理图片:[lena_color.jpg] 手动mask[mask.jpg] import numpy as np import cv2 ...
最新文章
- Farseer.net轻量级ORM开源框架 V1.x 入门篇:新版本说明
- 关于mysql的update、delete、和insert into能否使用别名问题
- Centos/RHEL上查看主板型号
- 1、Flutter_初体验_创建第一个应用_AndroidStudio_windows
- php写入rabbit速度,RabbitMQ 入门教程(PHP) 实现延迟功能
- 小米高管:已投大量精力研发手机AI芯片,造不造还没定
- win10分屏快捷键无法使用_Win10系统Win快捷键不能用怎么办_win10 Win快捷键无法使用如何解决-系统城...
- 计算机工程师英语简历模板,计算机软件工程师英文简历模板
- 教程|电脑PC微信多开
- 公共服务中,人脸识别的三类风险隐患与安全防护
- 是java运行时环境的缩写,java运行环境的英文缩写
- Allegro Design Entry CIS 和 Orcad Capture CIS 区别
- 阿里云物联网平台数据解析(python)
- 双拼和五笔输入法键盘位浮动贴图,适合初学者使用
- 知乎网的CSS命名规律研究
- python之emoji表情处理
- UML建模——活动图(Activity Diagram)
- 如何修改图片像素大小?调整图片大小的简单方法
- MTFCSGO准心设置
- NOIP2013提高组 day2