#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