文章目录
一、前言
Hilditch算法参看资料:http://cis.k.hosei.ac.jp/~wakahara/Hilditch.c
Hilditch第二种算法:http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/azar/skeleton.html#algorithm
图像细化:
图像细化主要是针对二值图而言,所谓骨架,可以理解为图像的中轴,,一个长方形的骨架,是它的长方向上的中轴线,圆的骨架是它的圆心,直线的骨架是它自身,孤立点的骨架也是自身。我们来看看典型的图形的骨架(用粗线表示)
细化的算法有很多种,但比较常用的算法是查表法。细化是从原来的图中去掉一些点,但仍要保持原来的形状。实际上是保持原图的骨架。判断一个点是否能去掉是以8个相邻点(八连通)的情况来作为判据的,具体判据为:
1,内部点不能删除
2,鼓励点不能删除
3,直线端点不能删除
4,如果P是边界点,去掉P后,如果连通分量不增加,则P可删除
二、第一种算法
假设当前被处理的像素为p0,我们使用下图所示的8邻域表示方式。
我们处理的为二值图像,背景为黑色=0,要细化的前景物体像素值=255。
对于Hilditch算法来说,它并不是一个完全的并行算法,而是串行并行相结合。当前像素是否是能够删除的骨架点,不仅是由它周围的8邻域决定,而且和前面像素的判定结果有关。一个像素判定为可以删除,我们并不直接删除它,而是在目地图像中设置像素值为GRAY=128,这个信息可能会影响之后其它像素的判定。
当图像一次扫描迭代完成后,我们把所有置为GRAY的像素设置为0,从而删除它。
算法的描述如下。
- 迭代扫描当前图像
对于当前像素点,扫描它的8邻域:
如果邻域的像素值为255,则b[i]=1(i=0…8),像素值为128(GRAY,表示该像素点在前面的循环中被标记为删除),b[i]=-1;如果像素值为0,则b[i]=0。 - 下面会根据b[i]的值进行6个条件判断,如果条件满足,则会标记该像素值为GRAY(128)。
- b[0]=1,即当前像素必须为前景点。
- 1-abs(b1) + 1 – abs(b3) + 1 – abs(b5) + 1 – abs(b7) >= 1,该条件表示当前像素为边界点,即东西南北四个点至少有一个b[i]=0。
- abs(b1)+…+abs(b8)>=2, 该条件表示不能删除端点,即p0点周围只有一个点为1或-1的情况。
- 统计b1到b8等于1的数量,该数量值必须大于1,该条件表示不能删除端点。
- 连通性检测,使用下面的公式:
首先根据当前像素周围3*3域的值,记录d[9]数组,如果b[i]等于0,则d[i]=0, 否则d[i]=1,最后计算 d1-d1*d2*d3+d3-d3*d4*d5+d5-d5*d6*d7+d7-d7*d8*d1是否为1,为1则满足连通性,可以删除。
6.最后一个条件保证当轮廓是2个像素宽时,只删除一边。统计sum的值,当值为8时候,可以删除。
当这6个条件都满足时候,标记当前像素值为GRAY(128),然后在判断别的像素。当所有像素都扫描一遍后,完成一次迭代。
此时我们会把刚才标记为GARY的像素,都设置为0,真正的删除它,如果上一次循环已经没有标记删除的像素,则退出迭代,否则进行下一次迭代。
三、第二种算法
第二种算法描述和上面的并行算法很相似,特别是前2个条件一模一样,不同的是3,4两个条件,还有就是该描述算法并没有像上面算法那样,把一次迭代分成2个阶段。
此时我们使用的8邻域标记为:
下面看下它的算法描述:
- 复制目地图像到临时图像,对临时图像进行一次扫描,对于不为0的点,如果满足以下四个条件,则在目地图像中删除该点(就是设置该像素为0)
2<= p2+p3+p4+p5+p6+p7+p8+p9<=6
大于等于2会保证p1点不是端点或孤立点,因为删除端点和孤立点是不合理的,
小于等于6保证p1点是一个边界点,而不是一个内部点。
等于0时候,周围没有等于1的像素,所以p1为孤立点,等于1的时候,周围只有1个灰度等于1的像素,所以是端点(注:端点是周围有且只能有1个值为1的像素)。
- p2->p9的排列顺序中,01模式的数量为1,比如下面的图中,有p2p3 => 01, p6p7=>01,所以该像素01模式的数量为2。
- 之所以要01模式数量为1,是要保证删除当前像素点后的连通性。比如下面的图中,01模式数量大于1,如果删除当前点p1,则连通性不能保证。
- p2.p4.p8 = 0 or A(p2)!=1,A(p2)表示p2周围8邻域的01模式和。这个条件保证2个像素宽的垂直条不完全被腐蚀掉。(图下左)
- p2.p4.p6 = 0 or A(p4)!=1,A(p4)表示p4周围8邻域的01模式和。这个条件保证2个像素宽的水平条不完全被腐蚀掉。(图上右)
3.1 代码演示
代码参看
测试原图(684*342):
显然细化算法有问题。
3.1 算法优化及代码演示
在每行水平扫描的过程中,先判断每一点的左右邻居,如果都是黑点,则该点不做处理。另外,如果某个黑店被删除了,则跳过它的右邻居,处理下一点。对矩形这样做完一遍,水平方向会减少两像素。
然后我们再改垂直方向扫描,方法一样。
这样做一次水平扫描和垂直扫描,原图会“瘦”一圈
多次重复上面的步骤,知道图形不在变化为止算法优化后如下:
显然,比之前效果好些了。使用 测试原图(684*342) 耗时有点久(处理器i5-8300H)
测试图片2
代码运算速度优化,减少了运行时间,使用测试原图(684*342)(上面的图片)
参考与鸣谢
https://www.researchgate.net/signup.SignUp.html?ev=su_requestFulltext
优化算法:https://wenku.baidu.com/view/a74c003567ec102de2bd8915.html