现在的位置: 首页 > 综合 > 正文

基于高速标注的连通图操作1401:提取最大连通域、去除小面积区域

2018年11月06日 ⁄ 综合 ⁄ 共 10049字 ⁄ 字号 评论关闭

源码在最后,这是函数原型说明

函数效果演示,参见我的其它博客

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;
}

欢迎学习,批评,指正



抱歉!评论已关闭.