改进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 ...
随机推荐
- RabbitMQ之pika模块
发布/订阅 系统 send.py import pika import time s_conn = pika.BlockingConnection(pika.ConnectionParameters( ...
- 【Linux】CentOS 7.5 修改时区
1⃣️查看当前CentOS系统版本: [parallels@k8s-node2 ~]$ cat /etc/redhat-release CentOS Linux release 7.5.1804 (C ...
- Realm 配置
快速入门 本文档介绍了如何借助一个“数据库”来配置 Tomcat ,从而实现容器管理安全性.所要连接的这种数据库含有用户名.密码以及用户角色.你只需知道的是,如果使用的 Web 应用含有一个或多个 & ...
- 【题解】P5446 [THUPC2018]绿绿和串串(manacher)
[题解]P5446 [THUPC2018]绿绿和串串(manacher) 考虑对于一个串进行\(f\)操作,就是让他变成一个以最后一个节点为回文中心的回文串. 那么对于某个位置\(p\),假如它是一个 ...
- 洛谷$P4585\ [FJOI2015]$火星商店问题 线段树+$trie$树
正解:线段树+$trie$树 解题报告: 传送门$QwQ$ $umm$题目有点儿长我先写下题目大意趴$QwQ$,就说有$n$个初始均为空的集合和$m$次操作,每次操作为向某个集合内加入一个数$x$,或 ...
- 详解js的bind、call、apply
详解js的bind.call.apply 说明 虽然bind.call.apply都是js很基础的一块知识,但是我从未认真总结过这三者的区别. 由于公司后端是用的微服务架构,又没有中间层对接,导致前端 ...
- 智能反射表面(可重构智能表面)Large Intelligent surface 最新综述整理
闻道洛阳花正好,家家遮户春风.道人饮处百壶空.年年花下醉,看尽几番红. 此拐又从何处去,飘蓬一任西东.语声虽异笑声同.一轮清夜月,何处不相逢. ---- 临江仙·与刘拐 更多精彩内容请关注微信公众号 ...
- 学了java,我才发现台球还可以这样玩!
桌球小游戏的尝试 桌球是人们日常生活中都能接触到的一种娱乐活动,随着互联网技术的发展,手机上也有了很多桌球小游戏,让人们随时随地都能打两把. 今天分享一个用java编写的桌球小游戏 代码如下: ...
- 2020面试还搞不懂MyBatis?快看看这27道面试题!(含答案和思维导图)
前言 MyBatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建statem ...
- Linux下卸载oracle需要删除的文件
卸载oracle需要删除的文件 rm -rf /data1/oracle/app #oracle安装目录在/data1/oracle中 rm -rf /usr/local/bin/dbhome rm ...