C语言实现的二次遍历法提取连通分量
http://blog.csdn.net/pc1377318286/article/details/41414381 tip:这是这个算法的OpenCV接口版本链接地址
图像的最外框必须为黑色,添加黑色外框的部分代码我没有植入,使用时要特别注意
第一遍扫描检测联通状态,将其记录如静态线性链表中
第二遍扫描根据指针数组和静态线性链表恢复出图像
如果联通分量溢出,直接修改 int label[4096]={0};int labelcnt[4096]={0};int lcnt[4096]={0};
这三个数组的大小,关于图像数组的建立,请参见我的其它博客
如果提示堆栈溢出,在属性中修改堆栈大小即可,根据处理图像大小选择堆栈保留大小,建议在16M以上
输入图像:
提取结果:
操作源码:
void twopass(unsigned char image[Y_SIZE][X_SIZE],unsigned char imageget[Y_SIZE][X_SIZE]) { int i,j,cnt=0; int max=0,sec=0; int lmax; int lsec; int label[4096]={0}; int labelcnt[4096]={0}; int lcnt[4096]={0}; int *plabel= label; int num,numt; int l=0; int *pimage[Y_SIZE][X_SIZE]; int imageout[Y_SIZE][X_SIZE]; unsigned char a,b,c,d; for(i=1;i<Y_SIZE;i++) for(j=1;j<X_SIZE-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!=X_SIZE-2) ) { pimage[i-1][j+1]=NULL; } else if( (i==1) && (j==X_SIZE-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==X_SIZE-2) ) { pimage[i][j+1]=NULL; } if(image[i][j]==BLACK) pimage[i][j]=NULL; else { a=image[i-1][j-1]; b=image[i-1][j]; c=image[i-1][j+1]; d=image[i][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]; }//1 else if( (a==0) && (b!=0) && (c==0) && (d==0) ) { pimage[i][j]=pimage[i-1][j]; }//2 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) && (d==0) ) { pimage[i][j]=pimage[i-1][j-1]; }//5 else if( (a!=0) && (b==0) && (c!=0) && (d==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) && (c==0) && (d!=0) ) { pimage[i][j]=pimage[i-1][j-1]; }//7 else if( (a==0) && (b!=0) && (c!=0) && (d==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]; }//9 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 if( (a==0) && (b!=0) && (c!=0) && (d!=0) ) { pimage[i][j]=pimage[i-1][j]; }//11 else if( (a!=0) && (b==0) && (c!=0) && (d!=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; }//12 else if( (a!=0) && (b!=0) && (c==0) && (d!=0) ) { pimage[i][j]=pimage[i-1][j-1]; }//13 else if( (a!=0) && (b!=0) && (c!=0) && (d==0) ) { pimage[i][j]=pimage[i-1][j-1]; }//14 else if( (a!=0) && (b!=0) && (c!=0) && (d!=0) ) { pimage[i][j]=pimage[i-1][j-1]; }//15 } } for(i=0;i<Y_SIZE;i++) { for(j=0;j<X_SIZE;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<Y_SIZE;i++) for(j=0;j<X_SIZE;j++) { if(imageout[i][j]==lmax) imageget[i][j]=WHITE; else imageget[i][j]=BLACK; } }
期中的逻辑还可以再优化,为便于分析,列出了15条,事实上可以简化为6条
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