连通成分(连通域)标记算法(一) bwlabel算法的C++实现(基于opencv)

       在图像处理过程中,我们经常需要对图像进行连通成分(连通域)的提取操作,提取连通成分的算法也就成了我们一直在研究的一个算法。近期图像处理老师给了我们一个标记一张图中连通成分的任务,不同连通成分用不同的标签标记,要求算法效率高。我对其进行了简单思考,现在把我觉得我所想出来的几种算法中的最优的一个算法进行讲解。

      首先我们拿到一张图,假设是下面这张:

      图中黑色表示符合我们要求的值,从图中可以看出,图中有三个相互独立的黑色团,可以称之为三个独立的连通成分,而我们要做的就是把这三个连通成分在图中找出来并按照一定顺序给他们标上不同的标签,在一个连通成分中的像素点标签相同。

      那么我们可以怎么做呢?我是这么想的。

  1. 逐行扫描,将每一行中的连通成分标记起来;
  2. 扫描下一行时,判定是否与上一行的连通成分有相连。若有相连,则标记为上以行连通成分的标签。若与多个上一行的连通成分相连,则把这些标签保存到一个数组中,以方便建立一个标签等价表。
  3. 将等价的标签都转换为其等价表中最小的那个标签。(如1,2,3标签等价,则将标签为3的像素点的标签转换为2,再将标签为2的像素点的标签转换为1,最后实现连通成分中的各像点标签相同)。
  4. 将标签映射到一个从1开始的连续区域。

      可能这么说还是有些同学不懂,没关系,我们对照上面的图来分析一下:

      首先,我们可以逐行扫描,把每一行中的连通成分标记起来。如上面第二行就一个我们所需的像素值,那么给它标上标签1。

      然后再扫描下面一行,把这一行中连在一起的符合要求的像素点又附上一样的标签,但是我们发现,第三行中的两个黑色像素点与第二行中的那个已经标记的像素点是连在一起的,是同一个连通成分,应该附上相同的标签。所以我们在扫描后面的行的时候,就应该判断目前行中存在的连通域是否和上一行的某些连通域相连,如果相连,就赋予上一行的标签,说明它们是同一个连通域。

      当扫描到第四行时,我们发现这一行前两个黑色像素点是相连的,并且与上一行的两个黑色点相连,所以赋予上一行的标签1,但第三个黑色像素点是独立的,也没有与上一行的像素点相连,这时候就应该赋予它一个新的标签,标签1,我们已经用过,所以赋予它新的标签2,说明它是一个新的连通成分中的元素。当然,也可能它会通过下面行的一些连通成分和连通成分1连接起来,这些我们就后面再做处理。

      再往下扫描的时候,我们可能会发现某一行把上面两个标签不一样的连通成分连接起来了,那么它们应该属于同一个连通成分(上面这张图中没有这种情况),这个时候这一个连接两个不同标签的连通成分到底该赋予哪个标签呢?不要急,我们随便给它一个标签,就暂且给最先与它所连接的上一行连通成分的标签(如果是从左边扫描,则是左上连通成分的标签),那么右边与它连接的那个标签怎么处理呢?我们可以先判断一下目前扫描的这一行是否已经赋予了上一行的标签,如果已经赋予,并且目前按道理来说又要赋予另一个标签(即与它连接的第二个连通成分),那么我们就把第二个甚至第三个要赋予的标签和已经赋予给它的这个标签存储到一起,作为等价标签,后面再对这些标签进行处理。

       这样扫描一遍之后,基本所有连通成分都有一个标签了。当然也可能属于同一个连通成分的不同元素标签并不同,这时候我们就要把这些同一个连通成分中的不同标签进行处理了。怎么处理呢?还记得我们刚刚建立的等价标签表吗?我们只需要判断它们是不是等价标签,然后把它们合并起来就行了,把大的标签更好为更小的标签。为了节省时间,对每个连通成分其实只需要读取它的第一个像素点的标签就行了,所以并不需要对其中的所有像素点都进行标签更换。

      做到这里我们工作差不多就完成了,但是当时题目要求的是连续标签,所以这里再把之前的标签映射到一个从1开始的连续区域。这里停一下,有些同学可能会问,标签为什么不连续呢?我们可以看到刚刚标签合并

  • 18
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值