二值化图像8联通域标记

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

//基于区域生长法的连通域标记(C语言)

区域生长法利用区域生长的思想,一次生长过程可以标记一整个连通区,只需对图像进行一次扫描就能标记出所有连通区。算法描述如下:

Step1、输入待标记图像bitmap(二值化原图,SDRAM内,u16,只有0x0000与0xffff),初始化一个与输入图像同样尺寸的标记矩阵labelmap(SDRAM内,大小与二值化原图相同,u16,初值0x0000),一个队列queue(SDRAM内,大小与二值化原图相同)以及标记计数labelIndex (unsigned char,最大值255,初值0);

Step2、按从左至右、从上至下的顺序扫描bitmap,当扫描到一个未被标记的前景像素p时(0xffff,2个字节,unsigned short int),labelIndex加1,并在labelmap中标记p(相应点的值赋为labelIndex),同时,扫描p的八邻域点,若存在未被标记的前景像素,则在labelmap 中进行标记,并放入queue中,作为区域生长的种子;

Step3、当queue不为空时,从queue中取出一个生长种子点p1,扫描p1的八邻域点,若存在未被标记过的前景像素,则在labelmap中进行标记,并放入queue中;

Step4、重复Step3直至queue为空,一个连通区标记完成;

Step5、转到Step2,直至整幅图像被扫描完毕,得到标记矩阵labelmap和连通区的个数labelIndex。

该算法最坏情况下,将对每个像素点都进行一次八邻域搜索,算法复杂度为O(n)。

//辅助队列

typedef struct QNode

{

int data;

struct QNode *next;

}QNode;

typedef struct Queue

{

struct QNode* first;

struct QNode* last;

}Queue;

void PushQueue(Queue *queue, int data)

{

QNode *p = NULL;

//p = (QNode*)malloc(sizeof(QNode));

p->data = data;

if(queue->first == NULL)

{

queue->first = p;

queue->last = p;

p->next = NULL;

}

else

{

p->next = NULL;

queue->last->next = p;

queue->last = p;

}

}

int PopQueue(Queue *queue)

{

QNode *p = NULL;

int data;

if(queue->first == NULL)

{

return -1;

}

p = queue->first;

data = p->data;

if(queue->first->next == NULL)

{

queue->first = NULL;

queue->last = NULL;

}

else

{

queue->first = p->next;

}

//free(p); //p归到队列原始的SDRAM起始地址

return data;

}

static int NeighborDirection[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};//??

//搜索并标记当前像素的8邻域

void SearchNeighbor(unsigned char *bitmap, int width, int height, int *labelmap, int labelIndex, int pixelIndex, Queue *queue)

{

int searchIndex, i, length;

labelmap[pixelIndex] = labelIndex;

length = width * height;

for(i = 0;i < 8;i++)

{

searchIndex = pixelIndex + NeighborDirection[i][0] * width + NeighborDirection[i][1];//???

if(searchIndex > 0 && searchIndex < length &&

bitmap[searchIndex] == 0xffff255 && labelmap[searchIndex] == 0)

{

labelmap[searchIndex] = labelIndex;

PushQueue(queue, searchIndex);

}

}

}

//头步骤1

int ConnectedComponentLabeling(unsigned char *bitmap, int width, int height, int *labelmap) {

int cx, cy, index, popIndex, labelIndex = 0;

Queue *queue = NULL;

//queue = (Queue*)malloc(sizeof(Queue));

queue->first = NULL;

queue->last = NULL;

//memset(labelmap, 0, width * height); //labelmap初始化为0x0000

for(cy = 01; cy < height - 1; cy++)

{

for(cx = 01; cx < width - 1; cx++)

{

index = cy * width + cx;

if(bitmap[index] == 0xffff255 && labelmap[index] == 0) //改点为前景色,且未被标记,index为当前点坐标

{

labelIndex++;

SearchNeighbor(bitmap, width, height, labelmap, labelIndex, index, queue);

popIndex = PopQueue(queue);

while(popIndex > -1)//当前的联通区域全部标记完成

{

SearchNeighbor(bitmap, width, height, labelmap, labelIndex, popIndex, queue);

popIndex = PopQueue(queue);

}

}

}

}

//free(queue);

return labelIndex;

}

相关文档
最新文档