相比上一篇文章,基于栈和深度优先的方法,两遍扫描的8邻域连通域标记算法更适合在 FPGA 或嵌入式环境下使用,是替代递归 flood_fill
的经典方法。
flood_fill方法可以参考我的另一篇文章:
findContours()边缘检测——C代码实现_findcontours函数参数-CSDN博客
两遍扫描CCL(Two-Pass Connected Component Labeling)的
1. 实现原理与算法流程
(1)第一遍扫描:赋予临时标签并记录等价关系
① 对每一个前景像素(非0):
-
按光栅顺序扫描每个像素(从左到右,从上到下)
-
对前景像素检查4个已处理的邻居位置:
-
左 (x-1, y)
-
上 (x, y-1)
-
左上 (x-1, y-1)
-
右上 (x+1, y-1)
-
-
若存在邻居标签:
-
取第一个遇到的标签作为主标签(chosen)
-
将其他邻居标签合并到主标签的并查集
-
当前像素继承主标签
-
-
若无邻居标签则分配新标签
② 标签归一化
-
通过并查集查找每个标签的根节点
-
为每个独立的连通域分配连续的最终标签(1,2,3...)
-
建立临时标签到最终标签的映射关系
(2)第二遍扫描:建立轮廓结构
-
再次扫描每个像素
-
对每个有标签的像素:
■ 通过映射表获取最终标签
■ 将像素坐标添加到对应标签的轮廓点集中
过滤轮廓(可选)
-
如:只保留
size >= 3
的轮廓(即面积太小的噪声区域被剔除); -
最后将有效的轮廓数组
Contour*
返回,并设置*num_contours
为其数量。