Zhang-Suen法

  • 原理—— Zhang-Suen法
  • 代码——python代码

原理—— Zhang-Suen法


细化法(又称形态学骨架法)是通过对光条纹不断地进行腐蚀操作,剥离光条纹边界,得到单像素宽度的光条纹连通线(又称骨架)的形态学处理方法。该方法是通过细化技术,将光条纹区域的细化曲线作为光条纹中心线。 由于细化法是基于形态学的方法,只是对光条纹骨架进行提取,没有考虑到光条纹的横截面灰度分布特点。因此,细化法提取的光条纹中心线精度有限。另一方面,由于该方法需要大量时间来进行反复的细化操作,提取算法的运算速度被大大降低。
细化的方法有很多种,下面介绍一种常用的Zhang-Suen细化算法。细化算法的一般分为以下四个步骤,
(1)标记将被删除的边界点;
(2)删除做了标记的点;
(3)继续标记将被删除的剩余的边界点;
(4)删除标记过的点。反复应用这个基本过程,直到再也没有被删除的点为止,此时算法终止,生成了该区域的骨架。
假设目标像素点标记为1,背景像素点标记为0,在图上图中 的八个邻域如图所示,Zhang-Suen算法第一步循环所有前景像素点,对满足如下公式(1-5)的像素标记点进行删除。第二步和第一步类似,满足公式(1-6)的像素 标记点记为删除。循环上述两个步骤,直到两步中没有像素标记点记为删除为止,输出图像即为二值图像细化后的骨架。

其中 N(P0)表示八个邻域中非零像素标记点的个数(二值图像只有0和1), S(P0)表示八个邻域中,按照顺时针方向,相邻两个像素出现0→1的次数,。
细化法由于需要做多次膨胀腐蚀操作,耗时较多,处理速度较慢,另外细化法对二值化的要求极高,往往因为噪声的干扰,将图像二值化会出现较大的误差。细化法属于形态学范畴,没有利用到灰度值之间的信息,因此对于复杂条件下的激光曲线提取效果较差。

代码——python代码

# 作用: zhang-sufa
# 作者: yeluo
import cv2
import numpy as np
import time
import matplotlib.pyplot as pltdef ROI(img):indexXY = np.argwhere(img > 0)minxy = np.min(indexXY, axis=0)maxxy = np.max(indexXY, axis=0)return minxy,maxxy
def neighbours(x,y,img):i = imgx1,y1,x_1, y_1 = x+1, y-1, x-1, y+1return [i[y1][x],  i[y1][x1],   i[y][x1],  i[y_1][x1],  # P2,P3,P4,P5i[y_1][x], i[y_1][x_1], i[y][x_1], i[y1][x_1]]  # P6,P7,P8,P9
def transitions(neighbours):n = neighbours + neighbours[0:1]  # P2, ... P9, P2return sum((n1, n2) == (0, 1) for n1, n2 in zip(n, n[1:]))
def ZhangSuenPlus(image):"""运行时间55s:param image::return:"""changing1 = changing2 = [(-1, -1)]while changing1 or changing2:# Step 1changing1 = []for y in range(1, len(image) - 1):for x in range(1, len(image[0]) - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, image)if (image[y][x] == 1 and    # (Condition 0)P4 * P6 * P8 == 0 and   # Condition 4P2 * P4 * P6 == 0 and   # Condition 3transitions(n) == 1 and # Condition 22 <= sum(n) <= 6):      # Condition 1changing1.append((x,y))for x, y in changing1: image[y][x] = 0# Step 2changing2 = []for y in range(1, len(image) - 1):for x in range(1, len(image[0]) - 1):P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, image)if (image[y][x] == 1 and    # (Condition 0)P2 * P6 * P8 == 0 and   # Condition 4P2 * P4 * P8 == 0 and   # Condition 3transitions(n) == 1 and # Condition 22 <= sum(n) <= 6):      # Condition 1changing2.append((x,y))for x, y in changing2: image[y][x] = 0#print changing1#print changing2flags = image>0image[flags] = 255#cv2.imshow("res",image)return image
def ZhangSuenPlus02(image):"""# 运行时间12.135秒:param image::return:"""indexXY = np.argwhere(image>0)minxy = np.min(indexXY,axis=0)maxxy = np.max(indexXY,axis=0)roi = image[minxy[0]-1:maxxy[0]+2,minxy[1]-1:maxxy[1]+2]changing1 = changing2 = [(-1, -1)]while changing1 or changing2:# Step 1changing1 = []for y in range(1, len(roi) - 1):for x in range(1, len(roi[0]) - 1):if roi[y][x] == 1:P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, roi)if (    # (Condition 0)P4 * P6 * P8 == 0 and   # Condition 4P2 * P4 * P6 == 0 and   # Condition 3transitions(n) == 1 and # Condition 22 <= sum(n) <= 6):      # Condition 1changing1.append((x,y))for x, y in changing1: roi[y][x] = 0# Step 2changing2 = []for y in range(1, len(roi) - 1):for x in range(1, len(roi[0]) - 1):if roi[y][x] == 1:P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, roi)if (   # (Condition 0)P2 * P6 * P8 == 0 and   # Condition 4P2 * P4 * P8 == 0 and   # Condition 3transitions(n) == 1 and # Condition 22 <= sum(n) <= 6):      # Condition 1changing2.append((x,y))for x, y in changing2: roi[y][x] = 0#print changing1#print changing2flags = roi>0roi[flags] = 255#cv2.imshow("res",image)return image
def ZhangSuenPlus03(image):"""# 运行时间9秒:param image::return:"""indexXY = np.argwhere(image>0)minxy = np.min(indexXY,axis=0)maxxy = np.max(indexXY,axis=0)roi = image[minxy[0]-1:maxxy[0]+2,minxy[1]-1:maxxy[1]+2]changing1 = changing2 = [(-1, -1)]while changing1 or changing2:indexXY = np.argwhere(roi>0)minxy = np.min(indexXY, axis=0)maxxy = np.max(indexXY, axis=0)roi = roi[minxy[0] - 1:maxxy[0] + 2, minxy[1] - 1:maxxy[1] + 2]# Step 1changing1 = []for y in range(1, len(roi) - 1):for x in range(1, len(roi[0]) - 1):if roi[y][x] == 1:P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, roi)if (    # (Condition 0)P4 * P6 * P8 == 0 and   # Condition 4P2 * P4 * P6 == 0 and   # Condition 3transitions(n) == 1 and # Condition 22 <= sum(n) <= 6):      # Condition 1changing1.append((x,y))for x, y in changing1: roi[y][x] = 0# Step 2changing2 = []for y in range(1, len(roi) - 1):for x in range(1, len(roi[0]) - 1):if roi[y][x] == 1:P2,P3,P4,P5,P6,P7,P8,P9 = n = neighbours(x, y, roi)if (   # (Condition 0)P2 * P6 * P8 == 0 and   # Condition 4P2 * P4 * P8 == 0 and   # Condition 3transitions(n) == 1 and # Condition 22 <= sum(n) <= 6):      # Condition 1changing2.append((x,y))for x, y in changing2: roi[y][x] = 0#print changing1#print changing2flags = roi>0roi[flags] = 255#cv2.imshow("res",image)return imagedef ZhangSuen_Bad(img):"""将灰度值转化为0和1,企图加速计算过程运行时间21.28sthresh计算失败:param img::return:"""copyMat = img.copy()k = 0row,col= img.shaperow = row-1col = col-1while(True):k= k+1stop= False# step1for i in range(1,row):for j in range(1,col):if img[i,j]>0:print(">0")p1 = 1 if img[i,j]>0 else 0p2 = 1 if img[i-1,j]>0 else 0p3 = 1 if img[i-1,j+1]>0 else 0p4 = 1 if img[i, j+1] > 0 else 0p5 = 1 if img[i+1, j+1] > 0 else 0p6 = 1 if img[i+1, j] > 0 else 0p7 = 1 if img[i+1, j-1] > 0 else 0p8 = 1 if img[i,j-1] > 0 else 0p9 = 1 if img[i-1, j-1] > 0 else 0np1 = p2+p3+p4+p5+p6+p7+p8+p9sp2 = 1 if (p2 == 0 and p3 == 1) else 0sp3 = 1 if (p3 == 0 and p4 == 1) else 0sp4 = 1 if (p4 == 0 and p5 == 1) else 0sp5 = 1 if (p5 == 0 and p6 == 1) else 0sp6 = 1 if (p6 == 0 and p7 == 1) else 0sp7 = 1 if (p7 == 0 and p8 == 1) else 0sp8 = 1 if (p8 == 0 and p9 == 1) else 0sp9 = 1 if (p9 == 0 and p2 == 1) else 0sp1 = sp2 + sp3 + sp4 + sp5 + sp6 + sp7 + sp8 + sp9if np1>=2 and np1<=6 and sp1==1 and(p2*p4*p6)==0 and (p4*p6*p8)==0:stop = TruecopyMat[i,j] = 0print("success")img = copyMat.copy()# step2for i in range(1,row):for j in range(1,col):if img[i,j]>0:print(">>")p2 = 1 if img[i - 1, j] > 0 else 0p3 = 1 if img[i - 1, j + 1] > 0 else 0p4 = 1 if img[i, j + 1] > 0 else 0p5 = 1 if img[i + 1, j + 1] > 0 else 0p6 = 1 if img[i + 1, j] > 0 else 0p7 = 1 if img[i + 1, j - 1] > 0 else 0p8 = 1 if img[i, j - 1] > 0 else 0p9 = 1 if img[i - 1, j - 1] > 0 else 0np1 = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9sp2 = 1 if (p2 == 0 and p3 == 1) else 0sp3 = 1 if (p3 == 0 and p4 == 1) else 0sp4 = 1 if (p4 == 0 and p5 == 1) else 0sp5 = 1 if (p5 == 0 and p6 == 1) else 0sp6 = 1 if (p6 == 0 and p7 == 1) else 0sp7 = 1 if (p7 == 0 and p8 == 1) else 0sp8 = 1 if (p8 == 0 and p9 == 1) else 0sp9 = 1 if (p9 == 0 and p2 == 1) else 0sp1 = sp2 + sp3 + sp4 + sp5 + sp6 + sp7 + sp8 + sp9if np1 >= 2 and np1 <= 6 and sp1 == 1 and (p2*p4*p8) == 0 and (p2*p6*p8) == 0:stop = TruecopyMat[i,j] = 0print("success")img = copyMat.copy()if(not stop):breakresImg = copyMat.copy()flags = resImg>0resImg[flags] = 255#print(k)# cv2.imshow("res",resImg)return resImgdef ZhangSuen(img):"""运行时间20.7s:param img::return:"""#indexXY = np.argwhere(img>0)#minxy = np.min(indexXY,axis=0)#maxxy = np.max(indexXY,axis=0)#roi = img[minxy[0]-3:maxxy[0]+4,minxy[1]-3:maxxy[1]+4]#flags = roi>0#roi[flags] = 255#cv2.imshow("roi",roi)#print(roi.shape)roi = imgk = 0row,col= roi.shapechanging1 = changing2 = [(-1, -1)]while changing1 or changing2:changing1 = []for i in range(1,row-1):for j in range(1,col-1):if roi[i,j]==1:p2 = roi[i-1,j]p3 = roi[i-1,j+1]p4 = roi[i, j+1]p5 = roi[i+1, j+1]p6 = roi[i+1, j]p7 = roi[i+1, j-1]p8 = roi[i,j-1]p9 = roi[i-1, j-1]np1 = p2+p3+p4+p5+p6+p7+p8+p9sp2 = 1 if (p2,p3)==(0,1) else 0sp3 = 1 if (p3,p4)==(0,1) else 0sp4 = 1 if (p4,p5)==(0,1) else 0sp5 = 1 if (p5,p6)==(0,1) else 0sp6 = 1 if (p6,p7)==(0,1) else 0sp7 = 1 if (p7,p8)==(0,1) else 0sp8 = 1 if (p8,p9)==(0,1) else 0sp9 = 1 if (p9,p2)==(0,1) else 0sp1 = sp2 + sp3 + sp4 + sp5 + sp6 + sp7 + sp8 + sp9if 2<=np1<=6 and sp1==1 and(p2*p4*p6)==0 and (p4*p6*p8)==0:changing1.append([i,j])for x,y in changing1:roi[x,y] = 0# step2changing2 = []for i in range(1,row-1):for j in range(1,col-1):if roi[i,j]==1:p2 = roi[i - 1, j]p3 = roi[i - 1, j + 1]p4 = roi[i, j + 1]p5 = roi[i + 1, j + 1]p6 = roi[i + 1, j]p7 = roi[i + 1, j - 1]p8 = roi[i, j - 1]p9 = roi[i - 1, j - 1]np1 = p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9sp2 = 1 if (p2, p3) == (0, 1) else 0sp3 = 1 if (p3, p4) == (0, 1) else 0sp4 = 1 if (p4, p5) == (0, 1) else 0sp5 = 1 if (p5, p6) == (0, 1) else 0sp6 = 1 if (p6, p7) == (0, 1) else 0sp7 = 1 if (p7, p8) == (0, 1) else 0sp8 = 1 if (p8, p9) == (0, 1) else 0sp9 = 1 if (p9, p2) == (0, 1) else 0sp1 = sp2 + sp3 + sp4 + sp5 + sp6 + sp7 + sp8 + sp9if 2<=np1<= 6 and sp1 == 1 and (p2*p4*p8) == 0 and (p2*p6*p8) == 0:#roi[i,j] = 0changing2.append([i,j])#print("success")for x,y in changing2:roi[x,y] = 0flags = roi>0roi[flags] = 255return roidef Draw():plt.figure()plt.subplot(131)plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))plt.title("origin image")plt.axis("off")plt.subplot(132)# plt.imshow(res,"gray")plt.title("res image")plt.axis("off")plt.subplot(133)# plt.imshow(resP,"gray")plt.title("resP image")plt.axis("off")plt.show()
# Draw()def XiHua(img):kernel_d = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))image_d = cv2.dilate(image, kernel_d, iterations=8)# cv2.namedWindow('dilate', cv2.WINDOW_NORMAL)# cv2.imshow('dilate', image_d)kernel_e = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))image_e = cv2.erode(image_d, kernel_e)image_ske = morphology.skeletonize(image_e)image_e = np.multiply(image_e, image_ske)return image_eif __name__ == "__main__":import osimport timefrom skimage import morphologyimage_path = './image/'save_path = './paper/zhang-suen/'sum_time = 0if not os.path.isdir(save_path): os.makedirs(save_path)for img in os.listdir(image_path):image = cv2.imread(os.path.join(image_path, img))gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)ret, thresh = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)time1 = time.time()result = ZhangSuen(thresh)time2 = time.time()temp_time = time2 - time1sum_time += temp_time# print("one image time: ", temp_time)# cv2.namedWindow('result', 0)# cv2.imshow('result', result)# cv2.waitKey(10)cv2.imwrite(os.path.join(save_path, img), result)per_time = sum_time / len(os.listdir(image_path))print("average image time:", per_time)

激光条纹中心提取——Zhang-Suen法python相关推荐

  1. 激光条纹中心提取——灰度中心法python

    激光条纹中心提取--灰度中心法python 灰度中心法 python代码 灰度中心法 灰度重心法是根据每行光条纹横截面内的灰度分布特征逐行进行处理,通过在行坐标的方向上,逐行计算提取光条纹区域的灰度重 ...

  2. 传统激光条纹中心提取算法研究现状

    传统激光条纹中心提取算法研究现状 前言 一.边缘法 二.中心法 三.阈值法 四. 细化法 五.极值法 六.灰度重心法 七.方向模板 八.曲线拟合法 九.Steger 前言 光条中心提取是将宽度大于1的 ...

  3. 激光条纹中心提取——方法总结

    激光条纹中心提取--方法总结 算法 优势 缺点 边缘法 处理速度快:适用于精度要求低的大型物体测量 存在很大误差:要求图像质量较好且结构光特性较高 中心法 适用于条纹质量好且形状规则的物体测量:精度高 ...

  4. 激光条纹中心提取——ZhangSuen法python

    ZhangSuen法: 论文连接:A fast parallel algorithm for thinning digital patterns 代码连接:https://github.com/bsd ...

  5. 【必备知识】:线激光条纹中心线提取算法导读

    线激光条纹特性 线激光器是由点激光器和前置透镜组成的.点激光器可以为He-Ne激光器或半导体激光器.相比较He-Ne激光器,半导体激光器因其输出光源具有发散性,更适合用于制作线激光器.需要说明的是,半 ...

  6. 中线提取算法_综述|线结构光中心提取算法研究发展

    摘 要: 线结构光扫描是三维重建领域的关键技术.光条纹中心提取算法是决定线结构光三维重建精度以及光条纹轮廓定位准确性的重要因素.本文详细阐述了光条纹中心提取算法的理论基础及发展历程,将现有算法分为三类 ...

  7. 灰度重心法提取光条纹中心

    灰度重心法提取激光光条纹中心其实是将光条纹截面的灰度值分布中的质心记作为光条纹的中心. 在一列线激光中先利用极值法求取光强最大的一点gmax,然后确定一个阀值K=gmax-g(g取10-20),在 ...

  8. opencv双目视觉标定,激光结构光提取,指定特征点获取世界坐标

    双目视觉标定,激光结构光提取,指定特征点获取世界坐标 标定方面 校正 结构光提取 二维点转换为三维点 总结 这学期在做双目视觉方面的事情,因为没人带,自己一个人踩了很多坑,因此在这写一点自己的总结心得 ...

  9. 灰色关联与TOPSIS法 —— python

    目录 1.简介 2.算法详解 2.1 指标正向化及标准化 2.2 找到最大最小参考向量 2.3 计算与参考向量的相关系数 2.4 求评分 3.实例分析 3.1 读取数据 3.2 数据标准化 3.3 得 ...

最新文章

  1. mysql中count的用法
  2. mysql 导入8msql文件_MySQL导入大容量SQL文件数据问题
  3. python项目-30 个惊艳的Python开源项目
  4. UI控件问题和XCode编译警告和错误解决方法集锦 (持续更新ing)
  5. linux桌面环境知乎,24 个值得尝试的 Linux 桌面环境 | Linux 中国
  6. arthas命令整理:基础命令、jvm相关、class相关命令
  7. PAT_B_1080_C++(25分)
  8. HDUOJ 1428
  9. redis将散裂中某个值自增_0基础掌握Django框架(49)Redis
  10. 使用客户端对象模型读取SharePoint列表数据
  11. C#开发高亮语法编辑器(一)——TextBox ,RichTextBox
  12. 百度编辑器ueditor自适应手机端
  13. Oracle归档日志管理
  14. 访问自己的网站有病毒提示,为什么?
  15. 为XHR对象所有方法和属性提供钩子 全局拦截AJAX
  16. bug宝典linux篇 LC_CTYPE: cannot change locale (en_US.UTF-8): No such file or directory(转)
  17. python连续写入数据之间用什么隔开_elasticsearch之使用Python批量写入数据
  18. TCP和HTTP的区别和联系
  19. 基于深度强化学习的路径规划笔记
  20. 【如何 在 HTML 页面中显示数学公式】

热门文章

  1. 网站服务器租用需要考虑清楚这些因素?
  2. view vue 存图片_小小vue2.0图片查看器
  3. 强大的万年历微信小程序源码-支持多做流量主模式
  4. 可以动态翻转和查询的 01最长不降序列
  5. 整形外科植入物行业调研报告 - 市场现状分析与发展前景预测
  6. 生成对抗:Pix2Pix
  7. 计算机控制 电机调速实验,ACT-DT3直流电机转速控制实验指导书
  8. 数据库报错“system01.dbf需要更多的恢复来保持一致性,数据库无法打开”的解决方法...
  9. webshell与一句话木马
  10. Anchorfree Hotspot Shield 去广告方法