图像细化算法
来源:互联网 发布:金桥软件公园 编辑:程序博客网 时间:2024/06/05 15:59
所谓的细化就是经过一层层的剥离,从原来的图中去掉一些点,但仍要保持原来的形状,直到得到图像的骨架。骨架,可以理解为图象的中轴。
好的细化算法一定要满足:
- 收敛性;
- 保证细化后细线的连通性
- 保持原图的基本形状
- 减少笔画相交处的畸变
- 细化结果是原图像的中心线
- 细化的快速性和迭代次数少
依据是否使用迭代运算可以分为两类:
- 非迭代算法
- 一次即产生骨架,如基于距离变换的方法。游程长度编码细化等。
- 迭代算法
即重复删除图像边缘满足一定条件的像素,最终得到单像素宽带骨架。
迭代方法依据其检查像素的方法又可以再分成
- 串行算法
是否删除像素在每次迭代的执行中是固定顺序的,它不仅取决于前次迭代的结果,也取决于本次迭代中已处理过像素点分布情况.
- 并行算法
像素点删除与否与像素值图像中的顺序无关,仅取决于前次迭代的结果
细化算法:
- Burning Algorithm
使用迭代的方法去除图像的边界, 可使用扫描线法来获取边界
- Zhang并行快速细化算法
模板:
p3 p2 p9
p4 p1 p8
p5 p6 p7
第一步,(其中p1为前景点,如果以下四个条件同时满足,则删除p1,即令p1=0)
1. 2<=N(p1)<=6 // 中心为黑点
2. Z0(p1)=1 // Nz为八邻域中黑点的数目
3. p2*p8*p6=0 // 避免图像被打断( 其反条件时不可删)
4. p4*p8*p6=0
其中,Z0(p1)是以p2,p3,...p8,p9为序时,这些点的值从0->1变化的次数
N(p1)是p1的非0邻近点的个数
被判定为删除的点暂不删除,但要加以记录。
等所有边界点都被判断完后,再一起将所有标记了的点删除,接下来进入第二阶段的删除步骤。
第二步,按照如下条件进行第二阶段的删除,条件为
1. 2<=N(p1)<=6 // 中心为黑点
2. Z0(p1)=1 // Nz为八邻域中黑点的数目
3. p2*p4*p6=0 // 避免图像被打断( 其反条件时不可删)
4. p2*p4*p8=0
同第一步一样,判定要删除的点只是加以记录而暂不删除,等待最后同时删除
对一副图像反复执行第一步与第二步的算法步骤,知道都没有可删除的点为止
我的zhang细化代码如下:
// p3 p2 p1
//**********使用zhang并行快速算法进行细化 p4 p p0
// p5 p6 p7
void ZhangThinning(int w,int h,BYTE *imgBuf)
{
int neighbor[8];
BYTE *mark=new BYTE[w*h];
memset(mark,0,w*h);
BOOL loop=TRUE;
int x,y,k;
int markNum=0;
while(loop)
{
loop=FALSE;
//第一步
markNum=0;
for(y=1;y<h-1;y++)
{
for(x=1;x<w-1;x++)
{
//条件1:p必须是前景点
if(imgBuf[y*w+x]==0 ) continue;
neighbor[0]= imgBuf[y*w+x+1] ;
neighbor[1]= imgBuf[(y-1)*w+x+1];
neighbor[2]= imgBuf[(y-1)*w+x];
neighbor[3]= imgBuf[(y-1)*w+x-1];
neighbor[4]= imgBuf[y*w+x-1];
neighbor[5]= imgBuf[(y+1)*w+x-1];
neighbor[6]= imgBuf[(y+1)*w+x];
neighbor[7]= imgBuf[(y+1)*w+x+1];
//条件2:2<=N(p)<=6
int np=(neighbor[0]+neighbor[1]+neighbor[2]+neighbor[3]+neighbor[4]+neighbor[5]+neighbor[6]+neighbor[7])/255;
if(np<2 || np>6) continue;
//条件3:S(p)=1
int sp=0;
for(int i=1;i<8;i++)
{
if(neighbor[i]-neighbor[i-1]==255)
sp++;
}
if(neighbor[0]-neighbor[7]==255)
sp++;
if(sp!=1) continue;
//条件4:p2*p0*p6=0
if(neighbor[2]&neighbor[0]&neighbor[6]!=0)
continue;
//条件5:p0*p6*p4=0
if(neighbor[0]&neighbor[6]&neighbor[4]!=0)
continue;
//标记删除
mark[w*y+x]=1;
markNum++;
loop=TRUE;
}
}
//将标记删除的点置为背景色
if(markNum>0)
{
for(y=0;y<h;y++)
{
for(x=0;x<w;x++)
{
k=y*w+x;
if(mark[k]==1)
{
imgBuf[k]=0;
}
}
}
}
//第二步
markNum=0;
for(y=1;y<h-1;y++)
{
for(x=1;x<w-1;x++)
{
//条件1:p必须是前景点
if(imgBuf[y*w+x]==0 ) continue;
neighbor[0]= imgBuf[y*w+x+1] ;
neighbor[1]= imgBuf[(y-1)*w+x+1];
neighbor[2]= imgBuf[(y-1)*w+x];
neighbor[3]= imgBuf[(y-1)*w+x-1];
neighbor[4]= imgBuf[y*w+x-1];
neighbor[5]= imgBuf[(y+1)*w+x-1];
neighbor[6]= imgBuf[(y+1)*w+x];
neighbor[7]= imgBuf[(y+1)*w+x+1];
//条件2:<=N(p)<=6
int np=(neighbor[0]+neighbor[1]+neighbor[2]+neighbor[3]+neighbor[4]+neighbor[5]+neighbor[6]+neighbor[7])/255;
if(np<2 || np>6) continue;
//条件3:S(p)=1
int sp=0;
for(int i=1;i<8;i++)
{
if(neighbor[i]-neighbor[i-1]==255)
sp++;
}
if(neighbor[0]-neighbor[7]==255)
sp++;
if(sp!=1) continue;
//条件4:p2*p0*p4==0
if(neighbor[2]&neighbor[0]&neighbor[4]!=0)
continue;
//条件5:p2*p6*p4==0
if(neighbor[2]&neighbor[6]&neighbor[4]!=0)
continue;
//标记删除
mark[w*y+x]=1;
markNum++;
loop=TRUE;
}
}
//将标记删除的点置为背景色
for(y=0;y<h;y++)
{
for(x=0;x<w;x++)
{
k=y*w+x;
if(mark[k]==1)
{
imgBuf[k]=0;
}
}
}
}
}
判断一个点是否能去掉, 要根据它的八个相邻点的情况来判断。(中间的点)
(1)不能删,因为它是个内部点,我们要求的是骨架,如果连内部点也删了,骨架也会被掏空的;
(2)不能删,和(1)是同样的道理;
(3)可以删,这样的点不是骨架;
(4)不能删,因为删掉后,原来相连的部分断开了;
(5)可以删,这样的点不是骨架;
(6)不能删,因为它是直线的端点,如果这样的点删了,那么最后整个直线也被删了,剩不下什么;
总结:
(1)内部点不能删除;
(2)孤立点不能删除;
(3)直线端点不能删除;
(4)如果P是边界点,去掉P后,如果连通分量不增加,则P可以删除。
- Hilditch、Pavlidis、Rosenfeld细化算法
这类算法则是在程序中直接运算,根据运算结果来判定是否可以删除点的算法,差别在于不同算法的判定条件不同。
Hilditch算法使用于二值图像,比较普通,是一般的算法;
Pavlidis算法通过并行和串行混合处理来实现,用位运算进行特定模式的匹配,所得的骨架是8连接的,使用于0-1二值图像;
Rosenfeld算法是一种并行细化算法,所得的骨架形态是8-连接的,使用于0-1二值图像。
(后两种算法的效果要更好一些,但是处理某些图像时效果一般,第一种算法使用性强些。)
- 索引表细化算法
经过预处理后得到待细化的图像是0、1二值图像。像素值为1的是需要细化的部分,像素值为0的是背景区域。基于索引表的算法就是依据一定的判断依据,所做出的一张表,然后根据魔鬼要细化的点的八个邻域的情况查询,若表中元素是1,若表中元素是1,则删除该点(改为背景),若是0则保留。因为一个像素的8个邻域共有256中可能情况,因此,索引表的大小一般为256。
查找表为二值图像处理提供了简洁而有效的方法。考虑一个像素的3乘3邻域。由于在这个邻域范围有9个像素,每个像素有两个状态(二值图像,取0,1),那么整个邻域不同状态的总数量为2^9=512 .这样,我们可以相对不同的情况(512种),来安排对应的输出值,而这512种可能是事先预知的,给每一个单元(一共9个单元)分别安排不同的权值,
1 8 64
2 16 128
4 32 256
也就是2的不同幂次,0,1,2,3。。。 8次幂
那么,某种状态数值就是加权值的和。
比如,
下面一种邻域组合:
0 1 0
1 1 0
0 0 1
它的值=2+8+16+256=282
这样的话,我们通过一个数值,就可以表达一种3乘3邻域的一种空间分布状态。
- 图像细化算法
- 图像细化算法大全
- 快速图像细化算法
- C#图像细化:Hilditch细化算法
- JAVA图像细化:Hilditch细化算法
- 细化处理(二值图像)Hilditch细化算法
- Matlab的图像细化算法(详细实现)
- C#写的图像细化算法
- 图像处理之Zhang Suen细化算法
- 图像处理之Zhang Suen细化算法
- 二值图像快速细化算法
- 图像细化
- 图像细化
- 图像细化
- 图像细化
- 图像细化
- 图像细化
- 细化算法
- Button 点击切换背景
- Android中如何修改系统时间
- Android 中 -Java中byte[]转String问题
- undefined reference to '__android_log_print' 的解决
- 误删数据文件的处理(环境为linux)
- 图像细化算法
- [我的作品]魔法瓶
- 将jpeg文件转换成.h文件
- UIAlertView用法
- python3.3 遍历文件夹及文件 小例
- Java初始化顺序
- cglib简单的小实例
- android手机root后的安全问题
- 缓存(Cache)使用用法