真这么难吗?或许的方法不当。
我学习图像处理算法的步骤是:先看论文或者书上的算法原理,然后下载别人写的代码,然后把代码拿来测试。按理说这个流程下来就可以掌握这个算法的应用了,可是我却困难重重,搞得我好没自信呀,又不傻又不呆,为什么我愣是没学会?
困难一: 找不到好的算法说明原理,网上的很多文章都是转的,对于算法原理基本都是简而言之;论文中总是改进的**算法,我想看最基础的最原始的那个算法呀,这个都还没懂看改进的也不会看懂呀;书上的算法原理也有些地方不明白;
困难二:看懂了算法原理,代码的实现又看不懂了,根据原理能推出哪一大段代码是什么作用,但是为什么编还是没搞懂;更可气的是看懂了的代码,运行出来却没有应有的效果,哭了,好郁闷。
昨天今天都在搞这个图像细化算法:
重点学习了 Hilditch细化算法
Hilditch 细化算法的步骤为:
对图像从左向右从上向下迭代每个像素,是为一个迭代周期。在每个迭代周期中,对于每一个像素p,如果它同时满足6个条件,则标记它。在当前迭代周期结束时,则把所有标记的像素的值设为背景值。如果某次迭代周期中不存在标记点(即满足6个条件的像素),则算法结束。假设背景值为0,前景值为1,则:
6个条件为:
(I):p 为1,即p不是背景;
(2):x1,x3,x5,x7不全部为1(否则把p标记删除,图像空心了);
(3):x1~x8 中,至少有2个为1(若只有1个为1,则是线段的端点。若没有为1的,则为孤立点);
(4):p的8连通联结数为1;
联结数指在像素p的3*3邻域中,和p连接的图形分量的个数:
image
上图中,左图的4连通联结数是2,8连通联结数是1,而右图的4联通联结数和8联通联结数都是2。
4连通联结数计算公式是:
image
8连通联结数计算公式是:
image其中,
image
至于公式怎么来的就不管了,直接用就行了。
(5)假设x3已经标记删除,那么当x3为0时,p的8联通联结数为1;
(6)假设x5已经标记删除,那么当x5为0时,p的8联通联结数为1。
/////////////////////////////////////////////////////////////////////////
//Hilditch细化算法
//功能:对图象进行细化
//参数:image:代表图象的一维数组
// lx:图象宽度
// ly:图象高度
// 无返回值
void ThinnerHilditch(void *image, unsigned long lx, unsigned long ly)
{
char *f, *g;
char n[10];
unsigned int counter;
short k, shori, xx, nrn;
unsigned long i, j;
long kk, kk11, kk12, kk13, kk21, kk22, kk23, kk31, kk32, kk33, size;
size = (long)lx * (long)ly;
g = (char *)malloc(size);
if(g == NULL)
{
printf("error in allocating memory!\n");
return;
}
f = (char *)image;
for(i=0; i<lx; i++)
{
for(j=0; j<ly; j++)
{
kk=i*ly+j;
if(f[kk]!=0)
{
f[kk]=1;
g[kk]=f[kk];
}
}
}
counter = 1;
do
{
printf("%4d*",counter);
counter++;
shori = 0;
for(i=0; i<lx; i++)
{
for(j=0; j<ly; j++)
{
kk = i*ly+j;
if(f[kk]<0)
f[kk] = 0;
g[kk]= f[kk];
}
}
for(i=1; i<lx-1; i++)
{
for(j=1; j<ly-1; j++)
{
kk=i*ly+j;
if(f[kk]!=1) //
continue;
kk11 = (i-1)*ly+j-1;
kk12 = kk11 + 1;
kk13 = kk12 + 1;
kk21 = i*ly+j-1;
kk22 = kk21 + 1;
kk23 = kk22 + 1;
kk31 = (i+1)*ly+j-1;
kk32 = kk31 + 1;
kk33 = kk32 + 1;
if((g[kk12]&&g[kk21]&&g[kk23]&&g[kk32])!=0)//不全为1
continue;
nrn = g[kk11] + g[kk12] + g[kk13] + g[kk21] + g[kk23] +
g[kk31] + g[kk32] + g[kk33];
if(nrn <= 1) //8邻域的点至少两个是1
{
f[kk22] = 2;//
?标记什么
continue;
}
n[4] = f[kk11];
n[3] = f[kk12];
n[2] = f[kk13];
n[5] = f[kk21];
n[1] = f[kk23];
n[6] = f[kk31];
n[7] = f[kk32];
n[8] = f[kk33];
n[9] = n[1];//?
xx = 0;
/
/************************************为什么这个for循环代表8联通连接数公式*********************
for(k=1; k<8; k=k+2)
{
if((!n[k])&&(n[k+1]||n[k+2]))
xx++;
}
if(xx!=1) //p的8联通连接数是1
{
f[kk22] = 2;
continue;
}
if(f[kk12] == -1)//图像不是二值图吗 为啥f[kk12]能取到-1,取到-1 //代表该点被标记删除了吗?假设x3已经标记删除,则x3=0时,8联通连接数为1
{
f[kk12] = 0;
n[3] = 0;
xx = 0;
for(k=1; k<8; k=k+2)
{
if((!n[k])&&(n[k+1]||n[k+2]))
xx++;
}
if(xx != 1)
{
f[kk12] = -1;
continue;
}
f[kk12] = -1;
n[3] = -1;
}
if(f[kk21]!=-1)//假设x5已经标记删除,则x5=0时,8联通连接数为1
{
f[kk22] = -1;
shori = 1;
continue;
}
f[kk21] = 0;
n[5] = 0;
xx = 0;
for(k=1; k<8; k=k+2)
{
if((!n[k])&&(n[k+1]||n[k+2]))
{
xx++;
}
}
if(xx == 1)
{
f[kk21] = -1;
f[kk22] = -1;//
最终p点标记为删除点
shori =1;
}
else
f[kk21] = -1;
//**********************************************
}
}
}while(shori);
free(g);
}
一个迭代周期是指一次循环吗?
更可气的是,这段代码,我测试了一个二值图像,根本运行不出效果来,但是网上的代码大部分都是这样的。
我想努力学好图像处理算法,同事我也知道自己存在很多问题,只是难于发现自己到底是哪里有问题,希望这个领域的前辈能指导一下我,多谢啦。非常勿扰啦。偶已经很伤心啦。