实现二值图像连通区标记之区域生长法
实现 图像 区域 标记 连通 生长
2023-09-14 09:10:28 时间
连通区标记是最主要的图像处理算法之中的一个。该算法中,按从左至右、从上至下的顺序,对整幅图像进行扫描,通过比較每一个前景像素的邻域进行连通区标记,并创建等效标记列表。最后,合并等效标记列表,并再次扫描图像以更新标记。算法的长处的是通俗易懂,缺点是须要两次扫描图像,效率不高。
区域生长法利用区域生长的思想,一次生长过程能够标记一整个连通区,仅仅需对图像进行一次扫描就能标记出全部连通区。算法描写叙述例如以下:
- 输入待标记图像bitmap,初始化一个与输入图像相同尺寸的标记矩阵labelmap,一个队列queue以及标记计数labelIndex;
- 按从左至右、从上至下的顺序扫描bitmap,当扫描到一个未被标记的前景像素p时,labelIndex加1,并在labelmap中标记p(对应点的值赋为labelIndex),同一时候,扫描p的八邻域点,若存在未被标记的前景像素,则在labelmap中进行标记,并放入queue中,作为区域生长的种子;
- 当queue不为空时,从queue中取出一个生长种子点p1,扫描p1的八邻域点,若存在未被标记过的前景像素,则在labelmap中进行标记,并放入queue中;
- 反复3直至queue为空,一个连通区标记完毕;
- 转到2,直至整幅图像被扫描完毕,得到标记矩阵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); return data; } static int NeighborDirection[8][2] = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; 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] == 255 && labelmap[searchIndex] == 0){ labelmap[searchIndex] = labelIndex; PushQueue(queue, searchIndex); } } } 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); for(cy = 1; cy < height - 1; cy++){ for(cx = 1; cx < width - 1; cx++){ index = cy * width + cx; if(bitmap[index] == 255 && labelmap[index] == 0){ 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; }
相关文章
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 图像滤镜艺术—保留细节的磨皮滤镜之PS实现
- python实现图像灰度处理
- 【说站】python如何实现图像等比缩放
- matlab 实现二值图像孔洞填充函数imfill()
- 通过卷积实现图像均值模糊
- 最佳实践|用腾讯云AI图像能力实现AI作画
- 查找表实现高效的图像超分辨率!论文/代码速递2022.10.31!
- 参数减半、与CLIP一样好,视觉Transformer从像素入手实现图像文本统一
- Photoshop打包实现AI图像论文,英伟达在实时视频上PS之路上越走越远
- MySQL实现图像存储的简易方法(mysql存储图片类型)
- 管理MySQL用户表:实现更高数据安全性(mysql用户表)
- 备份Oracle 整点备份:实现数据安全保障(oracle整点)
- Linux完美实现GPT分区格式教程(linux转gpt分区)
- CentOS6.5配置VNCServer实现图形化访问桌面
- 探究:Linux实现原子操作(linux原子操作实现)
- MySQL添加字段给表快速实现(mysql为表添加字段)
- MySQL中实现精确浮点数类型的Real类型介绍(mysqlreal类型)
- 用PaddlePaddle实现图像分类-DenseNet(动态图版)
- C语言中打印特殊图案的实现代码
- PHP实现将HTML5中Canvas图像保存到服务器的方法