• 实现二值图像连通区标记之区域生长法


    http://blog.csdn.net/songzitea/article/details/26105609

    连通区标记是最基本的图像处理算法之一。该算法中,按从左至右、从上至下的顺序,对整幅图像进行扫描,通过比较每个前景像素的邻域进行连通区标记,并创建等效标记列表。最后,合并等效标记列表,并再次扫描图像以更新标记。算法的优点的是通俗易懂,缺点是需要两次扫描图像,效率不高。

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

    1. 输入待标记图像bitmap,初始化一个与输入图像同样尺寸的标记矩阵labelmap,一个队列queue以及标记计数labelIndex;
    2. 按从左至右、从上至下的顺序扫描bitmap,当扫描到一个未被标记的前景像素p时,labelIndex加1,并在labelmap中标记p(相应点的值赋为labelIndex),同时,扫描p的八邻域点,若存在未被标记的前景像素,则在labelmap中进行标记,并放入queue中,作为区域生长的种子;
    3. 当queue不为空时,从queue中取出一个生长种子点p1,扫描p1的八邻域点,若存在未被标记过的前景像素,则在labelmap中进行标记,并放入queue中;
    4. 重复3直至queue为空,一个连通区标记完成;
    5. 转到2,直至整幅图像被扫描完毕,得到标记矩阵labelmap和连通区的个数labelIndex。

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

    [cpp] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. typedef struct QNode{  
    2.     int data;  
    3.     struct QNode *next;  
    4. }QNode;  
    5.   
    6. typedef struct Queue{  
    7.     struct QNode* first;  
    8.     struct QNode* last;  
    9. }Queue;  
    10.   
    11. void PushQueue(Queue *queue, int data){  
    12.     QNode *p = NULL;  
    13.     p = (QNode*)malloc(sizeof(QNode));  
    14.     p->data = data;  
    15.     if(queue->first == NULL){  
    16.         queue->first = p;  
    17.         queue->last = p;  
    18.         p->next = NULL;  
    19.     }  
    20.     else{  
    21.         p->next = NULL;  
    22.         queue->last->next = p;  
    23.         queue->last = p;  
    24.     }  
    25. }  
    26.   
    27. int PopQueue(Queue *queue){  
    28.     QNode *p = NULL;  
    29.     int data;  
    30.     if(queue->first == NULL){  
    31.         return -1;  
    32.     }  
    33.     p = queue->first;  
    34.     data = p->data;  
    35.     if(queue->first->next == NULL){  
    36.         queue->first = NULL;  
    37.         queue->last = NULL;  
    38.     }  
    39.     else{  
    40.         queue->first = p->next;  
    41.     }  
    42.     free(p);  
    43.     return data;  
    44. }  
    45.   
    46. static int NeighborDirection[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};  
    47.   
    48. void SearchNeighbor(unsigned char *bitmap, int width, int height, int *labelmap,   
    49.                     int labelIndex, int pixelIndex, Queue *queue){  
    50.     int searchIndex, i, length;  
    51.     labelmap[pixelIndex] = labelIndex;  
    52.     length = width * height;  
    53.     for(i = 0;i < 8;i++){  
    54.         searchIndex = pixelIndex + NeighborDirection[i][0] * width + NeighborDirection[i][1];  
    55.         if(searchIndex > 0 && searchIndex < length &&   
    56.             bitmap[searchIndex] == 255 && labelmap[searchIndex] == 0){  
    57.             labelmap[searchIndex] = labelIndex;  
    58.             PushQueue(queue, searchIndex);  
    59.         }  
    60.     }  
    61. }  
    62.   
    63. int ConnectedComponentLabeling(unsigned char *bitmap, int width, int height, int *labelmap){  
    64.     int cx, cy, index, popIndex, labelIndex = 0;  
    65.     Queue *queue = NULL;  
    66.     queue = (Queue*)malloc(sizeof(Queue));  
    67.     queue->first = NULL;  
    68.         queue->last = NULL;  
    69.     memset(labelmap, 0, width * height);  
    70.     for(cy = 1; cy < height - 1; cy++){  
    71.         for(cx = 1; cx < width - 1; cx++){  
    72.             index = cy * width + cx;  
    73.             if(bitmap[index] == 255 && labelmap[index] == 0){  
    74.                 labelIndex++;  
    75.                 SearchNeighbor(bitmap, width, height, labelmap, labelIndex, index, queue);  
    76.   
    77.                 popIndex = PopQueue(queue);  
    78.                 while(popIndex > -1){  
    79.                 SearchNeighbor(bitmap, width, height, labelmap, labelIndex, popIndex, queue);  
    80.                     popIndex = PopQueue(queue);  
    81.                 }  
    82.             }  
    83.         }  
    84.     }  
    85.     free(queue);  
    86.     return labelIndex;  
    87. }  
  • 相关阅读:
    MySQL总结二
    MySQL总结一
    Flink 流处理API之Join
    Flink 流处理API之二
    Flink 流处理API之一
    Flink ProcessFunction API
    Flink Window
    Spark性能优化
    BPM软件_K2百家讲坛 | 越秀地产:K2为房企数字化转型带来更多可能_全球领先的工作流引擎
    BPM软件_K2签约龙光地产,为集团实现“千亿目标”保驾护航_全业务流程管理专家
  • 原文地址:https://www.cnblogs.com/zkwarrior/p/5807491.html
Copyright © 2020-2023  润新知