改进Zhang Suen细化算法的C#实现
本文主要实现了改进Zhang Suen细化算法的C#实现,相关论文 :“牟少敏,杜海洋,苏平,查绪恒,陈光艺.一种改进的快速并行细化算法[J].微电子学与计算机,2013,(第1期)” 。这篇论文中关于Zhang Suen细化算法的描述,貌似存在问题。本文的算法中的意思是两次标记的点迭代后同时删除。而zhang快速算法,是分为两步删除边界点的。第一步迭代之后,已经做标记的点就需要删除了。如果两步可以放在一起删除的话,为什么不在一次迭代中将几个条件一起判断呢
一:Zhang-Suen细化算法介绍
Zhang-Suen细化算法通常是一个迭代算法,整个迭代过程分为两步:
Step One:循环所有前景像素点,对符合如下条件的像素点标记为删除:
1. 2 <= N(p1) <=6
2. S(P1) = 1
3. P2 * P4 * P6 = 0
4. P4 * P6 * P8 = 0
其中N(p1)表示跟P1相邻的8个像素点中,为前景像素点的个数
S(P1)表示从P2 ~ P9 ~ P2像素中出现0~1的累计次数,其中0表示背景,1表示前景
完整的P1 ~P9的像素位置与举例如下:
其中 N(p1) = 4, S(P1) = 3, P2*P4*P6=0*0*0=0, P4*P6*P8=0*0*1=0, 不符合条件,无需标记为删除。
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
循环上述两步骤,直到两步中都没有像素被标记为删除为止,输出的结果即为二值图像细化后的骨架。
二:代码实现步骤
#region 改进 Zhang-Suen algorithm
public Bitmap zhang_thinimage_improve(Bitmap bmp)
{
int imgWidth = bmp.Width;
int imgHeight = bmp.Height;
byte[,] BinaryArray = new byte[imgHeight, imgWidth];
int depth = Bitmap.GetPixelFormatSize(bmp.PixelFormat);
if (depth != )//判断位深度
{
int threshold = ;
BinaryArray = ToBinaryArray(bmp, out threshold);
}
else
{
BinaryArray = BinaryBitmapToBinaryArray(bmp);
}
int[] Zhangmude = new int[];
//int deletecount = 0;
List<Point> deletelist = new List<Point>();
while (true)
{
for (int y = ; y < imgHeight-; y++)
{
for (int x = ; x < imgWidth-; x++)
{
if (BinaryArray[y, x] == )
{
Zhangmude[] = ;
if (BinaryArray[y - , x] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y - , x + ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y, x + ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y + , x + ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y + , x] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y + , x - ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y, x - ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y - , x - ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
int whitepointtotal = ;
for (int k = ; k < ; k++)
{
//得到1的个数
whitepointtotal = whitepointtotal + Zhangmude[k];
}
if ((whitepointtotal >= ) && (whitepointtotal <= ))
{
//得到01的个数
int ap = ;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
//计算bp
int bp = ;
bp += Zhangmude[];
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
if (ap == || bp == || bp == || bp == || bp == || bp == || bp == || bp == || bp == || bp == || bp == )
{
if ((Zhangmude[] * Zhangmude[] * Zhangmude[] == ) && (Zhangmude[] * Zhangmude[] * Zhangmude[] == ))
{
deletelist.Add(new Point(y, x));
}
}
}
}
}
}
if (deletelist.Count() == ) break;
foreach (var deleteItem in deletelist)
{
BinaryArray[deleteItem.X, deleteItem.Y] = ;
}
deletelist.Clear();
for (int y = ; y < imgHeight-; y++)
{
for (int x = ; x < imgWidth-; x++)
{
if (BinaryArray[y, x] == )
{
Zhangmude[] = ;
if (BinaryArray[y - , x] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y - , x + ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y, x + ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y + , x + ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y + , x] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y + , x - ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y, x - ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
if (BinaryArray[y - , x - ] == ) Zhangmude[] = ;
else Zhangmude[] = ;
int whitepointtotal = ;
for (int k = ; k < ; k++)
{
//得到1的个数
whitepointtotal = whitepointtotal + Zhangmude[k];
}
if ((whitepointtotal >= ) && (whitepointtotal <= ))
{
//得到01的个数
int ap = ;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
if ((Zhangmude[] == ) && (Zhangmude[] == )) ap++;
//计算bp
int bp = ;
bp += Zhangmude[];
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
bp += Zhangmude[] << ;
if (ap == || bp == || bp == || bp == || bp == || bp == || bp == || bp == || bp == || bp == || bp == )
{
if ((Zhangmude[] * Zhangmude[] * Zhangmude[] == ) && (Zhangmude[] * Zhangmude[] * Zhangmude[] == ))
{
deletelist.Add(new Point(y, x));
}
}
}
}
}
}
if (deletelist.Count() == ) break;
foreach (var deleteItem in deletelist)
{
BinaryArray[deleteItem.X, deleteItem.Y] = ;
}
deletelist.Clear();
}
Bitmap dstBmp = BinaryArrayToBinaryBitmap(BinaryArray);
return dstBmp;
}
#endregion
还有一个问题需要注意,找到要删除的点之后不能立即删除,而是把找到的点做标记,等第一步全部遍历完之后才删除标记的点。同样第二步也是这样。
下面是实验结果:

本文借鉴了两篇博客,下面是原文地址:
https://blog.csdn.net/u011941438/article/details/54628836
https://blog.csdn.net/jia20003/article/details/52142992
改进Zhang Suen细化算法的C#实现的更多相关文章
- Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法
原文:Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法 [函数名称] 二值图像细化算法 WriteableBitmap ThinningProcess ...
- SSE图像算法优化系列三十二:Zhang\Guo图像细化算法的C语言以及SIMD指令优化
二值图像的细化算法也有很多种,比较有名的比如Hilditch细化.Rosenfeld细化.基于索引表的细化.还有Opencv自带的THINNING_ZHANGSUEN.THINNING_GUOHALL ...
- OpenCV学习(13) 细化算法(1)
程序编码参考经典的细化或者骨架算法文章: T. Y. Zhang and C. Y. Suen, "A fast parallel algorithm for thinning digita ...
- OpenCV学习(14) 细化算法(2)
前面一篇教程中,我们实现了Zhang的快速并行细化算法,从算法原理上,我们可以知道,算法是基于像素8邻域的形状来决定是否删除当前像素.还有很多与此算法相似的细化算法,只是判断的条件不一样. ...
- 手指静脉细化算法过程原理解析 以及python实现细化算法
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8672489.html 文中的一些图片以及思想很多都是参考https://www.cnblogs ...
- c++opencv中线条细化算法
要达到的效果就是将线条尽量细化成单像素,按照论文上的Hilditch算法试了一下,发现效果不好,于是自己尝试着写了一下细化的算法,基本原理就是从上下左右四个方向向内收缩. 1.先是根据图片中的原则确定 ...
- OpenCV学习(18) 细化算法(6)
本章我们在学习一下基于索引表的细化算法. 假设要处理的图像为二值图,前景值为1,背景值为0. 索引表细化算法使用下面的8邻域表示法: 一个像素的8邻域,我们可以用8位二进制表示,比如下面的8邻域,表示 ...
- OpenCV学习(17) 细化算法(5)
本章我们看下Pavlidis细化算法,参考资料http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/con ...
- OpenCV学习(16) 细化算法(4)
本章我们学习Rosenfeld细化算法,参考资料:http://yunpan.cn/QGRjHbkLBzCrn 在开始学习算法之前,我们先看下连通分量,以及4连通性,8连通性的概念: http://w ...
随机推荐
- 【2016常州一中夏令营Day2】
小 W 学数学[问题描述]为了测试小 W 的数学水平,果果给了小 W N 个点,问他这 N 个点能构成的三角形个数.[输入格式]第一行一个整数 N,代表点数.接下来 N 行,每行两个非负整数 X.Y, ...
- blink接收器
blink: [autorun] OPEN="AutoInst.exe" [AskRebootTitle] Dlg1=System Settings Change Dlg2=št ...
- 【转】Elasticsearch学习笔记
一.常用术语 索引(Index).类型(Type).文档(Document) 索引Index是含有相同属性的文档集合.索引在ES中是通过一个名字来识别的,且必须是英文字母小写,且不含中划线(-):可类 ...
- JDK、JRE、JVM、Android SDK、Android Studio
===================================================== 参考链接: JDK\JRE\JVM:https://www.cnblogs.com/bola ...
- POJ 2976 Dropping tests [二分]
1.题意:同poj3111,给出一组N个有价值a,重量b的物品,问去除K个之后,剩下的物品的平均值最大能取到多少? 2.分析:二分平均值,注意是去除K个,也就是选取N-K个 3.代码: # inclu ...
- HBase01
https://blog.csdn.net/weixin_42641909/article/details/89428976 1. HBase Shell操作连接集群hbase shell 2. 创建 ...
- windows下PostgreSQL 安装与配置
下载地址 https://www.postgresql.org/download/ Download the installer certified by EnterpriseDB for all s ...
- 使用SparkSql进行表的分析与统计
# 背景 我们的数据挖掘平台对数据统计有比较迫切的需求,而Spark本身对数据统计已经做了一些工作,希望梳理一下Spark已经支持的数据统计功能,后期再进行扩展. # 准备数据 在参考文献6中下载 ...
- Windows远程桌面管理--功能强大的远程批量管理工具【转】
曾经,我想着要是有一款绿色小巧,功能实用的远程桌面管理工具,其界面简洁,操作便捷,能够同时远程操作多台服务器,并且多台服务器间可以自由切换,适用于网站管理人员使用的工具该有多好,苍天不负有心人,终于出 ...
- 《美国纽约摄影学院摄影教材》PDF教材
下载地址: 美国纽约摄影学院摄影教材(上册).pdf 美国纽约摄影学院摄影教材(下册).pdf 欢迎你到纽约摄影学院来,我们急切地等待着开课,你们也在 跃跃欲试了.那就让我们马上开始吧! 你已 ...