改进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 ...
随机推荐
- C语言 屏幕截图 (GDI)
截取全屏幕 #include <windows.h> void echo(CHAR *str); int CaptureImage(HWND hWnd, CHAR *dirPath, ...
- 找不到 javax.servlet.http.HttpServletResponse 和 javax.servlet.http.HttpServletRequest 问题解决
时隔3个月,我又回来了!在做完毕设之后,由于对此过程中学到的一些东西疏于整理,所以当再次打开我的project时有些手足无措,以至于出现一些问题也要解决好半天,我知错! 今天的问题是: 开始搜到的解决 ...
- centos 利用mailx发送邮件
这里就已163或者126邮箱为例!阿里云的25号端口好像发送不了,用465端口可以发送成功! 安装:yum install -y mailx 然后就是修改配置文件 set ssl-verify=ign ...
- Vijos 1206 CoVH之再破难关 [BFS] [位运算]
1.题意:一个由01组成的4*4的矩阵,可以实现相邻元素交换位置的操作,给出初试状态和目标状态,试求最少操作数的方案: 2.输入输出:输入给出初试矩阵和目标矩阵:要求输出最小操作的次数: 3.分析:输 ...
- 图解Go里面的sync.Map了解编程语言核心实现源码
基础筑基 在大多数语言中原始map都不是一个线程安全的数据结构,那如果要在多个线程或者goroutine中对线程进行更改就需要加锁,除了加1个大锁,不同的语言还有不同的优化方式, 像在java和go这 ...
- 1072 开学寄语 (20分)C语言
下图是上海某校的新学期开学寄语:天将降大任于斯人也,必先删其微博,卸其 QQ,封其电脑,夺其手机,收其 ipad,断其 wifi,使其百无聊赖,然后,净面.理发.整衣,然后思过.读书.锻炼.明智.开悟 ...
- 小小知识点(五十一)——6G扬帆起航:拍赫兹通信与健康泛在网络助推6G新应用
转自IEEE科技纵览 https://weibo.com/ttarticle/p/show?id=2309404454066502631625 6G扬帆起航:拍赫兹通信与健康泛在网络助推6G新应用 ...
- 不只是安装,Kolla 让 OpenStack 运维变简单
使用 kolla 部署的 OpenStack 环境和传统直接安装的环境相比较,因为使用了全容器化部署,基本操作上有很大不同.对于初学者,操作变得更清晰和更简单了,但是如果你已经有了一定的经验,可能反而 ...
- Vue.js 入门 --- vue.js 安装
本博文转载 https://blog.csdn.net/m0_37479246/article/details/78836686 Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据 ...
- GDAL集成GEOS
因为要用到缓冲区分析,在使用Buffer的时候提示:ERROR 6: GEOS support not enabled,查了一下资料需要集成GEOS库.因为GDLA默认编译是没有集成GEOS库的. 现 ...