本文主要实现了改进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#实现的更多相关文章

  1. Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法

    原文:Win8 Metro(C#)数字图像处理--2.49Zhang二值图像细化算法  [函数名称]   二值图像细化算法      WriteableBitmap ThinningProcess ...

  2. SSE图像算法优化系列三十二:Zhang\Guo图像细化算法的C语言以及SIMD指令优化

    二值图像的细化算法也有很多种,比较有名的比如Hilditch细化.Rosenfeld细化.基于索引表的细化.还有Opencv自带的THINNING_ZHANGSUEN.THINNING_GUOHALL ...

  3. OpenCV学习(13) 细化算法(1)

    程序编码参考经典的细化或者骨架算法文章: T. Y. Zhang and C. Y. Suen, "A fast parallel algorithm for thinning digita ...

  4. OpenCV学习(14) 细化算法(2)

          前面一篇教程中,我们实现了Zhang的快速并行细化算法,从算法原理上,我们可以知道,算法是基于像素8邻域的形状来决定是否删除当前像素.还有很多与此算法相似的细化算法,只是判断的条件不一样. ...

  5. 手指静脉细化算法过程原理解析 以及python实现细化算法

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8672489.html 文中的一些图片以及思想很多都是参考https://www.cnblogs ...

  6. c++opencv中线条细化算法

    要达到的效果就是将线条尽量细化成单像素,按照论文上的Hilditch算法试了一下,发现效果不好,于是自己尝试着写了一下细化的算法,基本原理就是从上下左右四个方向向内收缩. 1.先是根据图片中的原则确定 ...

  7. OpenCV学习(18) 细化算法(6)

    本章我们在学习一下基于索引表的细化算法. 假设要处理的图像为二值图,前景值为1,背景值为0. 索引表细化算法使用下面的8邻域表示法: 一个像素的8邻域,我们可以用8位二进制表示,比如下面的8邻域,表示 ...

  8. OpenCV学习(17) 细化算法(5)

    本章我们看下Pavlidis细化算法,参考资料http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/con ...

  9. OpenCV学习(16) 细化算法(4)

    本章我们学习Rosenfeld细化算法,参考资料:http://yunpan.cn/QGRjHbkLBzCrn 在开始学习算法之前,我们先看下连通分量,以及4连通性,8连通性的概念: http://w ...

随机推荐

  1. 【2016常州一中夏令营Day2】

    小 W 学数学[问题描述]为了测试小 W 的数学水平,果果给了小 W N 个点,问他这 N 个点能构成的三角形个数.[输入格式]第一行一个整数 N,代表点数.接下来 N 行,每行两个非负整数 X.Y, ...

  2. P3157 动态逆序对 CDQ分治

    动态逆序对 CDQ分治 传送门:https://www.luogu.org/problemnew/show/P3157 题意: 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对 ...

  3. 前端vue——阿里图标的使用方法

    阿里图标库的官方网址:https://www.iconfont.cn/ 使用前需要先登录,这里有三种登录方式,本人使用的是新浪微博登录 第一步:找到你需要的图标,点击添加入库 第二步:点击右上角的购物 ...

  4. 2020 中国 .NET 开发者调查问卷

    随着.NET Core 3.1的发布,国内2019 中国.NET开发者峰会在上海的成功举办.从技术采用生命周期的角度来说,随着.NET Core 3.1的发布,有越来越多的厂商开始采用.NET Cor ...

  5. Google 开源的 Python 命令行库:深入 fire(一)

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...

  6. 【温故知新】Java web 开发(三)Form表单与上传下载文件

    简介:在一和二的基础之上,这次来记录下如何在页面提交表单数据,以及文件的上传和下载整个流程,请求也不仅限于GET了,也有POST了. 1. 为了方便,在 webapp 下直接新建一个 index.ht ...

  7. SofaBoot使用Nacos进行服务注册发现

    前提 最近创业公司的项目组基于业务需要,开发一套新的微服务,考虑到选用的组件必须是主流.社区活跃.生态完善以及方便迁移到云上等因素,引入了SOFAStack全家桶.微服务开发里面,一个很重要的功能就是 ...

  8. 【题解】CF1142B Lynyrd Skynyrd(倍增)

    [题解]CF1142B Lynyrd Skynyrd(倍增) 调了一个小时原来是读入读反了.... 求子段是否存在一个排列的子序列的套路是把给定排列看做置换,然后让给定的序列乘上这个置换,问题就转化为 ...

  9. 洛谷$P3647\ [APIO2014]$连珠线 换根$dp$

    正解:换根$dp$ 解题报告: 传送门! 谁能想到$9102$年了$gql$居然还没写过换根$dp$呢,,,$/kel$ 考虑固定了从哪个点开始之后,以这个点作为根,蓝线只可能是直上直下的,形如&qu ...

  10. $Noip2014/Luogu1351$ 联合权值 树形

    $Luogu$ $Description$ 给定一棵树,每两个距离为$2$的点之间可以产生"联合权值","联合权值"定义为这两个数的乘积.求最大的联合权值以及所 ...