二值图像连通标记矩阵计算

 
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <windows.h>

HANDLE hOut, hIn; /*标准输出输入句柄*/
COORD size = {200, 1000}; /*窗口大小*/
SMALL_RECT rc = {0, 0, 200-1, 50-1};
CONSOLE_CURSOR_INFO cursor = {1, FALSE}; /*光标信息,用于隐藏光标*/

typedef struct{
	unsigned short sc;
	unsigned short ec;
	unsigned short r;
	int label;
}RunNode_t;

typedef struct equivnode 
{
	int LabelA;
	int LabelB;
	struct equivnode *next;
}EquivNode;

typedef struct equivlist 
{
	EquivNode *head;
	int length;
}EquivList;

typedef struct MapListNode_tag
{
	int idx;
	struct MapListNode_tag* pNext;
}MapListNode_t;

typedef struct MapListList_tag
{
	MapListNode_t* pMapNodeList;
	struct MapListList_tag* pNext;
}MapListListNode_t;

typedef struct  
{
	int mode ; 
	int minarea ; 
	int minpixDiff;
}SparseInfoExtractCondition_t;

void DeleteEquivListHeadNode(EquivList *list) 
{
	EquivNode *killNode;
	if (list->head != NULL) 
	{
		killNode = list->head;
		list->head = killNode->next;
		free(killNode);
		list->length--;
	}
}

void DestroyEquivList(EquivList *list) 
{
	while (list->head != NULL)
	{
		EquivNode *killNode = list->head;
		list->head = killNode->next;
		free(killNode);
		list->length--;
	}
}

void UpdateRunNode(int *pTable , RunNode_t* pNode, int NodeNum)
{
	int i;
	for(i = 0 ; i < NodeNum ; i++)
	{
		pNode[i].label = pTable[pNode[i].label-1];
	}
}

void BWCreateRunNodeInfoEx(int* BW , int M ,int N ,
						   SparseInfoExtractCondition_t* pCondtion,
						   RunNode_t** ppRunNode, int *pRunNodeNum,
						   int* plabels, EquivList** ppEquivList)
{
	int *pr = NULL;
	int numRuns = 0;
	RunNode_t* pNode = NULL;
	int offset ;
	int i ,j ,k ,p;  
	int currentRow = -1;
	int nextLabel = 1;
	int firstRunOnPreviousRow = -1;
	int lastRunOnPreviousRow = -1;
	int firstRunOnThisRow = -1;
	EquivList* pEquivList = (EquivList*)malloc(sizeof(EquivList));

	int Mode = pCondtion->mode;
	int MinArea = pCondtion->minarea;
	int MinpixDiff = pCondtion->minpixDiff;

	//(1)Computer numRuns
	for (i = 0; i < N; i++)   //按行遍历
	{
		pr = &BW[i*M] ;    //第row行的头指针

		if (pr[0] != 0)
			numRuns++;        //本行的第一个元素就是一个Run的头 Run的数目+1

		for (j = 1; j < M; j++) {
			if ((pr[j] != 0) && (pr[j-1] == 0))   //01的模式就是Run
				numRuns++;                        //Run的总数+1
		}
	}
	*pRunNodeNum = numRuns;

	//(2) 生成 RunNode信息
	pNode = (RunNode_t*)malloc(numRuns*sizeof(RunNode_t));
	k = 0;
	for (i = 0; i < N; i++) 
	{
		pr = &BW[i*M]; 	//第row行的头指针

		j = 0;
		while (j < M) 
		{	  
			//遍历该行
			while (j < M && pr[j] == 0)
				j++; 						//找到第一个Run所在的行号

			if ((j < M) && (pr[j] != 0)) 
			{
				pNode[k].r = i ;	   //
				pNode[k].sc = j ;
				while (j < M && pr[j] )	 //走完这个Run
					j++;
				pNode[k].ec = j-1;	//这个是结尾
				pNode[k].label = 0;
				k++;		  //处理下一个Run
			}
		}
	}

	//(3)扫描标记 ,并统计Label 关系的
	printf("\n\n");
	printf("(2)打印等价关系对\n");
	pEquivList->head = NULL;
	pEquivList->length = 0;
	offset = 1;  //八邻域为1  ,四邻域为0
	for (k = 0; k < numRuns; k++) 
	{
		if (pNode[k].r == currentRow + 1) 
		{	
			//第k个Run与第k-1个Run在相邻的两行上
			firstRunOnPreviousRow = firstRunOnThisRow;	 //firstRunOnPreviousColumn指向第k-1个Run所在的列的第一个(最上面的)Run
			firstRunOnThisRow = k;
			lastRunOnPreviousRow = k-1;
			currentRow = pNode[k].r;
		}
		else if (pNode[k].r > (currentRow + 1)) 
		{
			/* 开始新列:前一列没有Run  直接进入下一轮循环*/
			firstRunOnPreviousRow = -1;
			lastRunOnPreviousRow = -1;
			firstRunOnThisRow = k;
			currentRow = pNode[k].r;
		}

		if (firstRunOnPreviousRow >= 0) 
		{
			p = firstRunOnPreviousRow;
			while (p <= lastRunOnPreviousRow && pNode[p].sc <= pNode[k].ec + offset) 
			{
				if ((pNode[k].ec >= pNode[p].sc-offset) && 
					(pNode[k].sc <= pNode[p].ec+offset)) //有交叉
				{
					if (pNode[k].label == 0) 
					{
						pNode[k].label = pNode[p].label;
					}
					else 
					{
						if (pNode[k].label != pNode[p].label) 
						{
							EquivNode *newNode = (EquivNode *)malloc(sizeof(EquivNode));
							newNode->LabelA = pNode[k].label;
							newNode->LabelB = pNode[p].label;
							newNode->next = pEquivList->head;
							pEquivList->head = newNode;
							pEquivList->length++;
							printf("%4d %4d\n" , newNode->LabelA , newNode->LabelB);
						}
					}
				}
				p++;
			}
		}

		if (pNode[k].label == 0) 
		{
			pNode[k].label = nextLabel;
			nextLabel++;
		}
	}
	*plabels =nextLabel-1;
	*ppRunNode = pNode;
	*ppEquivList = pEquivList;

	printf("\n\n(3) 打印初始RunNode信息\n");
	printf("  sc   ec    r   label \n");
	for(i=0;i<numRuns;i++)
	{
		printf("%4d ",pNode[i].sc);
		printf("%4d ",pNode[i].ec);
		printf("%4d ",pNode[i].r);
		printf("%4d ",pNode[i].label);
		printf("\n");
	}
}

void MapListAddNode(MapListNode_t* pNode , int Idx)
{
	MapListNode_t* pNodeTemp = malloc(sizeof(MapListNode_t));
	MapListNode_t* pNodeMove = pNode;
	pNodeTemp->idx = Idx;
	pNodeTemp->pNext = NULL;

	while(pNodeMove->pNext)
		pNodeMove = pNodeMove->pNext;

	pNodeMove->pNext = pNodeTemp;
}

void MapListListAddNode(MapListListNode_t* pListListNode ,MapListNode_t* pListNode)
{
	MapListListNode_t* pListListNodeMove = pListListNode;
	MapListListNode_t* pListListNodeNew = malloc(sizeof(MapListListNode_t));
	while(pListListNodeMove->pNext)
		pListListNodeMove = pListListNodeMove->pNext;

	pListListNodeNew->pMapNodeList = pListNode;
	pListListNodeNew->pNext = NULL;
	pListListNodeMove->pNext = pListListNodeNew;
}

void MapListListDeleteNode(MapListListNode_t* pListListNode ,MapListNode_t* pListNode)
{
	MapListListNode_t* pListListNodeMove = pListListNode;
	MapListListNode_t* pListListNodeKill = NULL;
	while(pListListNodeMove->pNext)
	{
		if(pListListNodeMove->pNext->pMapNodeList == pListNode)
		{
			pListListNodeKill = pListListNodeMove->pNext;
			pListListNodeMove->pNext = pListListNodeMove->pNext->pNext;
			free(pListListNodeKill); 
			break;
		}
		pListListNodeMove = pListListNodeMove->pNext;
	}

}
int MapListMinIdx(MapListNode_t* pNode)
{
	int min = 0x7FFFFFFF;
	while(pNode)
	{
		if(pNode->idx < min)
			min = pNode->idx;
		pNode = pNode->pNext;
	}
	return min;
}
MapListNode_t* MapListListFindIdx(MapListListNode_t* pMapListList ,int Idx)
{
	MapListNode_t* pMapListNodeHead = NULL;
	MapListNode_t* pMapNodeListMove = NULL;
	MapListListNode_t* pMapListListMove = pMapListList;
	while(pMapListListMove->pNext)
	{
		pMapListListMove = pMapListListMove->pNext;
		pMapListNodeHead = pMapListListMove->pMapNodeList;
		pMapNodeListMove = pMapListNodeHead;
		while(pMapNodeListMove)	
		{
			if(Idx == pMapNodeListMove->idx)
				return pMapListNodeHead;

			pMapNodeListMove = pMapNodeListMove->pNext;
		}
	}
	return NULL;
}

void MapListMerge(MapListNode_t* pMapListA , MapListNode_t* pMapListB)
{
	while(pMapListA->pNext)
		pMapListA = pMapListA->pNext;
	pMapListA->pNext = pMapListB;
}


void CreateMapTable(EquivList* pList ,int MapTableSize ,int **ppMapTable )
{
	int i,j,k;
	int labela,labelb;
	MapListNode_t* pMapNodeList = (MapListNode_t*)malloc(sizeof(MapListNode_t));
	MapListListNode_t* pMapListListNode = NULL;
	MapListListNode_t* pMapListListforMove = NULL;
	MapListNode_t* pMapListforMove = NULL ;
	int *pMapTableInit = NULL;
	pMapNodeList->idx = pList->head->LabelA;   
	pMapNodeList->pNext = NULL;
	MapListAddNode(pMapNodeList,pList->head->LabelB);

	DeleteEquivListHeadNode(pList);

	pMapListListNode = (MapListListNode_t*)malloc(sizeof(MapListListNode_t));
	pMapListListNode->pMapNodeList = NULL;
	pMapListListNode->pNext = NULL;
	MapListListAddNode(pMapListListNode,pMapNodeList);

	while(pList->length)
	{
		MapListNode_t* pMapListFindA = NULL;
		MapListNode_t* pMapListFindB = NULL;
		labela = pList->head->LabelA;
		labelb = pList->head->LabelB;
		pMapListFindA = MapListListFindIdx(pMapListListNode,labela);
		pMapListFindB = MapListListFindIdx(pMapListListNode,labelb);

		if(pMapListFindA)
		{
			if(pMapListFindB)
			{
				if (pMapListFindA!=pMapListFindB)
				{			
					MapListMerge(pMapListFindA,pMapListFindB);
					MapListListDeleteNode(pMapListListNode,pMapListFindB);
				}
			}
			else
			{
				MapListAddNode(pMapListFindA,labelb);
			}
		}
		else
		{
			if(pMapListFindB)
			{
				MapListAddNode(pMapListFindB,labela);
			}
			else
			{
				pMapNodeList = (MapListNode_t*)malloc(sizeof(MapListNode_t));
				pMapNodeList->pNext = NULL;
				pMapNodeList->idx = labela;
				MapListAddNode(pMapNodeList,labelb);
				MapListListAddNode(pMapListListNode,pMapNodeList);
			}
		}
		DeleteEquivListHeadNode(pList);
	}

	printf("\n\n(4)打印等价链表:\n");
	pMapListListforMove = pMapListListNode;
	while (pMapListListforMove->pNext)
	{
		pMapListforMove = pMapListListforMove->pNext->pMapNodeList;
		while(pMapListforMove)
		{
			printf("%4d",pMapListforMove->idx);
			pMapListforMove = pMapListforMove->pNext;
		}
		printf("\n");
		pMapListListforMove = pMapListListforMove->pNext;
	}

	pMapTableInit = (int*)malloc(MapTableSize*sizeof(int));
	printf("\n\n打印初始关系表");
	for(i = 1 ; i <= MapTableSize ; i++ )
	{
		pMapListforMove = MapListListFindIdx(pMapListListNode,i);
		if(pMapListforMove)
		{
			pMapTableInit[i-1] = MapListMinIdx(pMapListforMove);
			printf("%3d " ,pMapTableInit[i-1]);
		}
		else
		{
			pMapTableInit[i-1] = i;
			printf("%3d " ,i);
		}
	}

	printf("\n\n打印对应关系表");
	*ppMapTable = (int*)malloc(MapTableSize*sizeof(int));
	(*ppMapTable)[0] = 1;
	printf("%3d ",(*ppMapTable)[0]);
	k = 2;
	for(i = 1 ; i < MapTableSize ; i++ )
	{
		j = 0;

		while(j<i)
		{
			if(pMapTableInit[j] == pMapTableInit[i])
			{
				(*ppMapTable)[i] = (*ppMapTable)[j];
				break;
			}
			j++;
		}

		if(j == i)
			(*ppMapTable)[i] = k++;

		printf("%3d ",(*ppMapTable)[i]);
	}
}

void BWCreateRunNodeInfo(int* BW , int M ,int N ,
						 SparseInfoExtractCondition_t* pCondtion,
						 RunNode_t** ppRunNode, int *pRunNodeNum)
{
	EquivList* pEquivList = NULL;
	int *pMapTable = NULL;
	int labels = 0;
	BWCreateRunNodeInfoEx(BW ,M ,N ,pCondtion,ppRunNode, pRunNodeNum,&labels ,&pEquivList);

	if(pEquivList->length)
	{
		CreateMapTable( pEquivList, labels,&pMapTable);
		UpdateRunNode(pMapTable,*ppRunNode,*pRunNodeNum);
	}
}

void UpadateBWData(int* BW, int M ,RunNode_t* pNode , int NodeNum)
{
	int k = 0 , p = 0;
	int *pr = NULL;
	for (k = 0; k < NodeNum; k++) 
	{
		pr = &BW[pNode[k].r*M + pNode[k].sc];
		for (p = 0; p < pNode[k].ec - pNode[k].sc + 1; p++)
			*pr++ = pNode[k].label;
	}
}

#define M 40
#define N 30

int main() 
{
	int i = 0, j = 0;
	RunNode_t* pRunNode = NULL;
	int RunNum = 0;
	SparseInfoExtractCondition_t ExtractCondition;
	int BW[N][M];

	hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleWindowInfo(hOut, TRUE, &rc);
	SetConsoleScreenBufferSize(hOut, size);
	SetConsoleCursorInfo(hOut, &cursor);


	srand( (unsigned)time( NULL ) );
	printf("(1) 打印实验矩阵\n");
	for(i = 0; i< N ;i++)
	{
		for( j =0 ;j < M;j++ )
		{
			if(j == 0)
				printf("\n");

			BW[i][j] = (rand()%100)<40;
			printf("%3d ",BW[i][j]);
		}
	}

	ExtractCondition.minarea = 10;
	ExtractCondition.minpixDiff = 10;
	ExtractCondition.mode = 1;
	BWCreateRunNodeInfo((int*)BW ,M ,N ,&ExtractCondition,&pRunNode, &RunNum);

	printf("\n\n");
	printf("(5) 打印最后RunNode信息\n");
	printf("  sc  ec   r   label\n");
	for(i=0;i<RunNum;i++)
	{
		printf("%4d ",pRunNode[i].sc);
		printf("%4d ",pRunNode[i].ec);
		printf("%4d ",pRunNode[i].r);
		printf("%4d ",pRunNode[i].label);
		printf("\n");
	}

	//(4)根据统计表建立,影射关系表
	UpadateBWData((int*)BW,M,pRunNode,RunNum);


	//打印矩阵
	printf("\n(6) 生成最后的连通标记矩阵");
	for(i = 0; i< N ;i++)
	{
		for( j =0 ;j<M;j++ )
		{
			if(j == 0)
				printf("\n");
			printf("%3d ",BW[i][j]);
		}
	}
	printf("\n");
}


参考资料:

(1) 稀疏信息提取:读Matlab7.7 IPT的bwlabel函数(一)——bwlabel1的Python描述  http://blog.sina.com.cn/s/blog_4513dde60100o6oz.html 

(2) MATLAB 使用的bwlabel1.c    http://code.google.com/p/mirone/source/browse/trunk/mex/bwlabel1.c?spec=svn1874&r=1874

(3) 连通关系合并 http://blog.csdn.net/caiqi1123/article/details/7101168

 

你可能感兴趣的:(二值图像连通标记矩阵计算)