图像分割算法及其实现

  最近这段时间所完成的是一个关于图像处理和模式识别的算法的实现,这个算法是基于论文《Object tracking based on image segmentation and pattern matching》来用C语言实现的,OpenCV作为其图片显示的框架。初步实现了简单图像的完全分割,并且能将不同的物体进行标记,以实现下一步的跟踪。这里主要完成的图像分割的实现。分割的简单图片如下所示:

  此算法的目的为将图片中的三个物体分割出来,并对每个物体进行标记。具体算法如下所示:

  算法实现分为以下几个模块,分别为:权重计算,种子点判断,种子点生长三部分。

  首先是种子点的判断,其公式为:

  

  C语言实现为:

  1.寻找R,G,B的最大值:

    

        //寻找最大的RGB值
for(h = 0; h < height; h++)
{
k = h*width*3;
for(w = 0; w < width; w++)
{
l = w*3;
B = *(data + k + l);
G = *(data + k + l + 1);
R = *(data + k + l + 2);

if(R > Rmax) Rmax = R;
if(G > Gmax) Gmax = G;
if(B > Bmax) Bmax = B;
}
}

  2.根据阈值找出种子点

  

/* ------------------------------------------------------------------------ *
* 计算connection-weights,标记种子点 *
* ------------------------------------------------------------------------
*/
for(h=1; h<height-1; h++)
{
k = h*width*3;
for(w=1; w<width-1; w++)
{
l = 3*w;
for(m=0; m<8; m++)
{
n = (h + h_offset[m])*width*3;
o = 3*(w + w_offset[m]);
p = n + o;

B = *(data + l + k);
G = *(data + l + 1 + k);
R = *(data + l + 2 + k);

B_8 = *(data + p);
G_8 = *(data + 1 + p);
R_8 = *(data + 2 + p);

Wij_R = Rmax/(1 + abs(R - R_8));
Wij_G = Gmax/(1 + abs(G - G_8));
Wij_B = Bmax/(1 + abs(B - B_8));
//得到最小的Wij
Wij[m] = Wij_R;
if(Wij_G < Wij[m]) Wij[m] = Wij_G;
if(Wij_B < Wij[m]) Wij[m] = Wij_B;
}
//get pixel i's sum of Wij
Wij_sum = Wij[0] + Wij[1] + Wij[2] + Wij[3] + Wij[4] + Wij[5] + Wij[6] + Wij[7];

// printf("%d\n",Wij_sum);

//set flag of leader cell
if(Wij_sum > THRESHOLD)
{
leadercell[h*width + w] = 1;
}
}
}

  3.对种子点进行生长

  

    for(m = 0; m < height*width; m++)
{
if(leadercell[m] == 1)
{
first_leadercell = m;
break;
}
}

self_excitation[first_leadercell] = 1;
global_inhibitor = 1;
n = 0;
o = 0;
p = 0;

while(leadercell_label)
{
if(global_inhibitor == 0)
{
for(m = 0; m < height*width; m++)
{
if(self_excitation[m] == 1)
{
self_excitation[m] = 0;
inhibitor[m] = 0;
leadercell[m] = 0;
}
}
for(m = 0; m < height*width; m++)
{
if(leadercell[m] == 1)
{
first_leadercell = m;
break;
}
}

self_excitation[first_leadercell] = 1;
inhibitor[m] = 1;
// global_inhibitor = 1;
region_label++;
num++;
}
else
{
for(h = 1; h < height; h++)
{
k = h*width*3;
for(w = 1; w < width; w++)
{
l = 3*w;
if(self_excitation[h*width + w] == 0 && inhibitor[h*width + w] == 0)
{
for(m = 0; m < 8; m++)
{
n = (h + h_offset[m])*width*3;
o = 3*(w + w_offset[m]);
p = n + o;

B = *(data + l + k);
G = *(data + l + 1 + k);
R = *(data + l + 2 + k);

B_8 = *(data + p);
G_8 = *(data + 1 + p);
R_8 = *(data + 2 + p);
Xj = self_excitation[(h + h_offset[m])*width + (w + w_offset[m])];

Wij_R = Rmax/(1 + abs(R - R_8));
Wij_G = Gmax/(1 + abs(G - G_8));
Wij_B = Bmax/(1 + abs(B - B_8));
//得到最小的Wij
Wij_x = Wij_R;
if(Wij_G < Wij_x) Wij_x = Wij_G;
if(Wij_B < Wij_x) Wij_x = Wij_B;
Wij_Xj[m] = Wij_x*Xj;
}
Wij_sum = Wij_Xj[0] + Wij_Xj[1] + Wij_Xj[2] + Wij_Xj[3] + Wij_Xj[4] + Wij_Xj[5] + Wij_Xj[6] + Wij_Xj[7];
if(Wij_sum > THRESHOLD_Z)
{
self_excitation[h*width + w] = 1;
inhibitor[h*width + w] = 1;
label[h*width + w] = region_label;
/* *(data_image1 + l + k) = 255;
*(data_image1 + l + k + 1) = 0;
*(data_image1 + l + k + 2) = 0;
*/
}
else
{
self_excitation[h*width + w] = 0;
inhibitor[h*width + w] = 0;
}
}
else if(self_excitation[h*width + w] == 1 && inhibitor[h*width + w] == 1)
{
self_excitation[h*width + w] = 1;
inhibitor[h*width + w] = 0;
}
}//for w
}//for h
}
global_inhibitor = 0;
leadercell_label = 0;
for(m = 0; m < height*width; m++)
{
global_inhibitor = global_inhibitor | inhibitor[m];
}
for(m = 0; m < height*width; m++)
{
leadercell_label = leadercell_label | leadercell[m];
}
num1++;
}//while

 

  最后得到的分割结果为:

  

 

  验证结果能够对物体进行分割,并能标示出来,下一步实验为更多的物体:

  其分割结果为:

  可以发现对图像中的所有物体均能分割和标记,效果很好,但是存在一个问题就是对复杂的图像分割效果不是很理想,需要下一步继续学习数字图像处理的知识,深入理解图像分割的原理,在这个基础上能够实现更复杂图像的分割。

  令一个是需要在算法再下功夫,能够让速度更快,不再进行重复扫描,从而能在连续视频中使用。

posted on 2011-12-06 20:45  Step by step!  阅读(2485)  评论(2)    收藏  举报

导航