博客已转移至个人网站(http://www.p-chao.com)
源码在最后,这是函数原型说明
函数效果演示,参见我的其它博客
http://blog.csdn.net/pc1377318286/article/details/41414507
以及:
http://blog.csdn.net/pc1377318286/article/details/30966877
#define WHITE 255
#define BLACK 0
#include <stdio.h>
#include <malloc.h>
#include "cv.h"
int cvMaxLable( IplImage* imgin , IplImage* imgout );
int twopass(unsigned char* image,unsigned char* imageget,int size[2]);
int imareaopen(unsigned char *image,unsigned char *imageget,int areasize,int size[2]);
以上是调用声明,其中后两个函数不需要OpenCV的声明
第一个:
int cvtwopass(unsigned char* image,unsigned char* imageget,int size[2])
{
int i,j,cnt=0;
int max=0,sec=0;
int lmax;
int lsec;
int *label=(int *)calloc(size[0]*size[1]/2,sizeof(int)); //索引数组,plabel直接指向的标记索引号区间
int *labelcnt=(int *)calloc(size[0]*size[1]/2,sizeof(int)); //标注数组,处理过标记冲突的索引号,其数组最终大小即为连通图个数
int *lcnt=(int *)calloc(size[0]*size[1]/8,sizeof(int)); //计数数组,统计每个连通图的大小
int *plabel= label;
int num,numt;
int l=0;
int xstep;
unsigned char a,b,c,d,e;
int **imageout;
int ***pimage;
imageout = (int **)malloc(size[1]*sizeof(int));
pimage = (int ***)malloc(size[1]*sizeof(int *));
for(i=0;i<size[1];i++)
{
imageout[i] = (int *)malloc(size[0]*sizeof(int));
pimage[i] = (int **)malloc(size[0]*sizeof(int *));
}
if(size[0]%4 == 0)
xstep = size[0];
else
xstep = size[0] + 4 - size[0]%4;
for(i=1;i<size[1];i++)
for(j=1;j<size[0]-1;j++)
{
if( (i==1) && (j==1) )
{
pimage[i-1][j-1]=NULL;
pimage[i-1][j]=NULL;
pimage[i-1][j+1]=NULL;
pimage[i][j-1]=NULL;
}
else if( (i==1) && (j!=1) && (j!=size[0]-2) )
{
pimage[i-1][j+1]=NULL;
}
else if( (i==1) && (j==size[0]-2) )
{
pimage[i-1][j+1]=NULL;
pimage[i][j+1]=NULL;
}
else if( (i!=1) && (j==1))
{
pimage[i][j-1]=NULL;
}
else if( (i!=1) && (j==size[0]-2) )
{
pimage[i][j+1]=NULL;
}
if(*(image + i*xstep + j) == BLACK)
{
pimage[i][j]=NULL;
}
else
{
a= *(image + (i-1)*xstep + j-1);
b= *(image + (i-1)*xstep + j);
c= *(image + (i-1)*xstep + j+1);
d= *(image + i*xstep + j-1);
e= *(image + i*xstep + j);
if( (a==0) && (b==0) && (c==0) && (d==0) )
{
plabel++;cnt++;
pimage[i][j]=plabel;
}//0
else if( (a==0) && (b==0) && (c!=0) && (d==0) )
{
pimage[i][j]=pimage[i-1][j+1];
}//3
else if( (a==0) && (b==0) && (c==0) && (d!=0) )
{
pimage[i][j]=pimage[i][j-1];
}//4
else if( (a!=0) && (b==0) && (c!=0) )
{
pimage[i][j]=pimage[i-1][j-1];
numt=*(pimage[i-1][j-1]);
if(numt==0)
{
numt=(((int)pimage[i-1][j-1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[numt]==0) break;
else numt=label[numt];
}
}
num=*(pimage[i-1][j+1]);
if(num==0)
{
num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(numt!=num) label[num]=numt;
}//6
else if( (a==0) && (b!=0) )
{
pimage[i][j]=pimage[i-1][j];
}//8
else if( (a==0) && (b==0) && (c!=0) && (d!=0) )
{
pimage[i][j]=pimage[i-1][j+1];
numt=*(pimage[i][j-1]);
if(numt==0)
{
numt=(((int)pimage[i][j-1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[numt]==0) break;
else numt=label[numt];
}
}
num=*(pimage[i-1][j+1]);
if(num==0)
{
num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(numt!=num) label[num]=numt;
}//10
else
{
pimage[i][j]=pimage[i-1][j-1];
}//15
}
}
for(i=0;i<size[1];i++)
{
for(j=0;j<size[0];j++)
{
if(pimage[i][j]!=NULL)
{
num=*(pimage[i][j]);
if(num==0)
{
num=(((int)pimage[i][j]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(labelcnt[num]==0)
{
l++;
labelcnt[num]=l;
}
imageout[i][j]=labelcnt[num];
lcnt[labelcnt[num]]++;
}
else imageout[i][j]=0;
}
}
for(i=0;i<l+1;i++)
{
if(lcnt[i]>max)
{
max=lcnt[i];
lmax=i;
}
}
for(i=0;i<l;i++)
if( (lcnt[i]>sec) && (lcnt[i]<max) )
{
sec=lcnt[i];
lsec=i;
}
for(i=0;i<size[1];i++)
for(j=0;j<size[0];j++)
{
if(imageout[i][j]==lmax) *(imageget + i*xstep +j) = WHITE;
else *(imageget + i*xstep +j) = BLACK;
}
for(i=0;i<size[1];i++)
{
free(imageout[i]);
free(pimage[i]);
}
free(imageout);
free(pimage);
free(label);
free(labelcnt);
free(lcnt);
return 0;
}
int cvMaxLable( IplImage* imgin , IplImage* imgout )
{
int x , y;
int size[2] = { imgin->width , imgout->height };
for( y = 0; y < imgin->height; y++ )
{
uchar* ptr = (uchar*)( imgin->imageData + y * imgin->widthStep );
for( x = 0; x < imgin->width; x++ )
{
if( x == 0 || y == 0 || x == imgin->width - 1 )
ptr[x] = 0;
}
}
cvtwopass( (unsigned char *)imgin->imageData,(unsigned char *)imgout->imageData,size);
return 0;
}
第二个:
int twopass(unsigned char* image,unsigned char* imageget,int size[2])
{
int i,j,cnt=0;
int max=0,sec=0;
int lmax;
int lsec;
int *label=(int *)calloc(size[0]*size[1]/2,sizeof(int)); //索引数组,plabel直接指向的标记索引号区间
int *labelcnt=(int *)calloc(size[0]*size[1]/2,sizeof(int)); //标注数组,处理过标记冲突的索引号,其数组最终大小即为连通图个数
int *lcnt=(int *)calloc(size[0]*size[1]/8,sizeof(int)); //计数数组,统计每个连通图的大小
int *plabel= label;
int num,numt;
int l=0;
unsigned char a,b,c,d,e;
int **imageout;
int ***pimage;
imageout = (int **)malloc(size[1]*sizeof(int));
pimage = (int ***)malloc(size[1]*sizeof(int *));
for(i=0;i<size[1];i++)
{
imageout[i] = (int *)malloc(size[0]*sizeof(int));
pimage[i] = (int **)malloc(size[0]*sizeof(int *));
}
for(i=1;i<size[1];i++)
for(j=1;j<size[0]-1;j++)
{
if( (i==1) && (j==1) )
{
pimage[i-1][j-1]=NULL;
pimage[i-1][j]=NULL;
pimage[i-1][j+1]=NULL;
pimage[i][j-1]=NULL;
}
else if( (i==1) && (j!=1) && (j!=size[0]-2) )
{
pimage[i-1][j+1]=NULL;
}
else if( (i==1) && (j==size[0]-2) )
{
pimage[i-1][j+1]=NULL;
pimage[i][j+1]=NULL;
}
else if( (i!=1) && (j==1))
{
pimage[i][j-1]=NULL;
}
else if( (i!=1) && (j==size[0]-2) )
{
pimage[i][j+1]=NULL;
}
if(*(image + i*size[0] + j) == BLACK)
{
pimage[i][j]=NULL;
}
else
{
a= *(image + (i-1)*size[0] + j-1);
b= *(image + (i-1)*size[0] + j);
c= *(image + (i-1)*size[0] + j+1);
d= *(image + i*size[0] + j-1);
e= *(image + i*size[0] + j);
if( (a==0) && (b==0) && (c==0) && (d==0) )
{
plabel++;cnt++;
pimage[i][j]=plabel;
}//0
else if( (a==0) && (b==0) && (c!=0) && (d==0) )
{
pimage[i][j]=pimage[i-1][j+1];
}//3
else if( (a==0) && (b==0) && (c==0) && (d!=0) )
{
pimage[i][j]=pimage[i][j-1];
}//4
else if( (a!=0) && (b==0) && (c!=0) )
{
pimage[i][j]=pimage[i-1][j-1];
numt=*(pimage[i-1][j-1]);
if(numt==0)
{
numt=(((int)pimage[i-1][j-1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[numt]==0) break;
else numt=label[numt];
}
}
num=*(pimage[i-1][j+1]);
if(num==0)
{
num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(numt!=num) label[num]=numt;
}//6
else if( (a==0) && (b!=0) )
{
pimage[i][j]=pimage[i-1][j];
}//8
else if( (a==0) && (b==0) && (c!=0) && (d!=0) )
{
pimage[i][j]=pimage[i-1][j+1];
numt=*(pimage[i][j-1]);
if(numt==0)
{
numt=(((int)pimage[i][j-1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[numt]==0) break;
else numt=label[numt];
}
}
num=*(pimage[i-1][j+1]);
if(num==0)
{
num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(numt!=num) label[num]=numt;
}//10
else
{
pimage[i][j]=pimage[i-1][j-1];
}//15
}
}
for(i=0;i<size[1];i++)
{
for(j=0;j<size[0];j++)
{
if(pimage[i][j]!=NULL)
{
num=*(pimage[i][j]);
if(num==0)
{
num=(((int)pimage[i][j]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(labelcnt[num]==0)
{
l++;
labelcnt[num]=l;
}
imageout[i][j]=labelcnt[num];
lcnt[labelcnt[num]]++;
}
else imageout[i][j]=0;
}
}
for(i=0;i<l+1;i++)
{
if(lcnt[i]>max)
{
max=lcnt[i];
lmax=i;
}
}
for(i=0;i<l;i++)
if( (lcnt[i]>sec) && (lcnt[i]<max) )
{
sec=lcnt[i];
lsec=i;
}
for(i=0;i<size[1];i++)
for(j=0;j<size[0];j++)
{
if(imageout[i][j]==lmax) *(imageget + i*size[0] +j) = WHITE;
else *(imageget + i*size[0] +j) = BLACK;
}
/* int **imageout;
int ***pimage;
imageout = (int **)malloc(size[1]*sizeof(int));
pimage = (int ***)malloc(size[1]*sizeof(int *));
for(i=0;i<size[1];i++)
{
imageout[i] = (int *)malloc(size[0]*sizeof(int));
pimage[i] = (int **)malloc(size[0]*sizeof(int *));
}*/
for(i=0;i<size[1];i++)
{
free(imageout[i]);
free(pimage[i]);
}
free(imageout);
free(pimage);
return 0;
}
第三个:
int imareaopen(unsigned char *image,unsigned char *imageget,int areasize,int size[2])
{
int i,j,cnt=0;
int max=0,sec=0;
int lmax;
int *label=(int *)calloc(size[0]*size[1]/2,sizeof(int)); //索引数组,plabel直接指向的标记索引号区间
int *labelcnt=(int *)calloc(size[0]*size[1]/2,sizeof(int)); //标注数组,处理过标记冲突的索引号,其数组最终大小即为连通图个数
int *lcnt=(int *)calloc(size[0]*size[1]/8,sizeof(int)); //计数数组,统计每个连通图的大小
int *plabel= label;
int num,numt;
int l=0;
unsigned char a,b,c,d;
int **imageout;
int ***pimage;
//申请等大数组空间
imageout = (int **)malloc(size[1]*sizeof(int));
pimage = (int ***)malloc(size[1]*sizeof(int *));
for(i=0;i<size[1];i++)
{
imageout[i] = (int *)malloc(size[0]*sizeof(int));
pimage[i] = (int **)malloc(size[0]*sizeof(int *));
}
for(i=1;i<size[1];i++)
for(j=1;j<size[0]-1;j++)
{
if( (i==1) && (j==1) )
{
pimage[i-1][j-1]=NULL;
pimage[i-1][j]=NULL;
pimage[i-1][j+1]=NULL;
pimage[i][j-1]=NULL;
}
else if( (i==1) && (j!=1) && (j!=size[0]-2) )
{
pimage[i-1][j+1]=NULL;
}
else if( (i==1) && (j==size[0]-2) )
{
pimage[i-1][j+1]=NULL;
pimage[i][j+1]=NULL;
}
else if( (i!=1) && (j==1))
{
pimage[i][j-1]=NULL;
}
else if( (i!=1) && (j==size[0]-2) )
{
pimage[i][j+1]=NULL;
}
if(*(image + i * size[0] + j)==BLACK) pimage[i][j]=NULL;
else
{
a=*(image + (i-1) * size[0] + j - 1);
b=*(image + (i-1) * size[0] + j);
c=*(image + (i-1) * size[0] + j + 1);
d=*(image + i * size[0] + j - 1);
if( (a==0) && (b==0) && (c==0) && (d==0) )
{
plabel++;cnt++;
pimage[i][j]=plabel;
}//0
else if( (a==0) && (b==0) && (c!=0) && (d==0) )
{
pimage[i][j]=pimage[i-1][j+1];
}//3
else if( (a==0) && (b==0) && (c==0) && (d!=0) )
{
pimage[i][j]=pimage[i][j-1];
}//4
else if( (a!=0) && (b==0) && (c!=0) )
{
pimage[i][j]=pimage[i-1][j-1];
numt=*(pimage[i-1][j-1]);
if(numt==0)
{
numt=(((int)pimage[i-1][j-1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[numt]==0) break;
else numt=label[numt];
}
}
num=*(pimage[i-1][j+1]);
if(num==0)
{
num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(numt!=num) label[num]=numt;
}//6
else if( (a==0) && (b!=0) )
{
pimage[i][j]=pimage[i-1][j];
}//8
else if( (a==0) && (b==0) && (c!=0) && (d!=0) )
{
pimage[i][j]=pimage[i-1][j+1];
numt=*(pimage[i][j-1]);
if(numt==0)
{
numt=(((int)pimage[i][j-1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[numt]==0) break;
else numt=label[numt];
}
}
num=*(pimage[i-1][j+1]);
if(num==0)
{
num=(((int)pimage[i-1][j+1]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(numt!=num) label[num]=numt;
}//10
else
{
pimage[i][j]=pimage[i-1][j-1];
}//15
}
}
for(i=0;i<size[1];i++)
{
for(j=0;j<size[0];j++)
{
if(pimage[i][j]!=NULL)
{
num=*(pimage[i][j]);
if(num==0)
{
num=(((int)pimage[i][j]-(int)label)/sizeof(int));
}
else
{
while(1)
{
if(label[num]==0) break;
else num=label[num];
}
}
if(labelcnt[num]==0)
{
l++;
labelcnt[num]=l;
}
imageout[i][j]=labelcnt[num];
lcnt[labelcnt[num]]++;
}
else imageout[i][j]=0;
}
}
//生成标注图像,并计数
for(i=0;i<size[1];i++)
{
for(j=0;j<size[0];j++)
{
if(lcnt[imageout[i][j]] > areasize )
{
*(imageget + i * size[0] + j) = WHITE;
}
else
{
*(imageget + i * size[0] + j) = BLACK;
}
}
}
for(i=0;i<size[1];i++)
{
free(imageout[i]);
free(pimage[i]);
}
free(imageout);
free(pimage);
free(label);
free(labelcnt);
free(lcnt);
return 0;
}
欢迎学习,批评,指正