图像连通域标记算法研究
搬以前写的博客【2014-03-01 08:09】
图像连通域标记算法研究 ConnectedComponent Labeling
最近在研究一篇复杂下背景文字检测的论文。
“Detecting Text in Natural Scenes with Stroke Width Transform ” CPVR 2010的文章,它主要探讨利用文字内部笔画宽度一致作为主要线索来检测文字的一个新奇的算法,当然,我不是想讨论文字检测,论文算法实施的过程中有一步涉及到图像连通域标记算法,在这里我遇到了一些问题,查阅了一些相关文章,所以想分享一下。
数字图像处理中有介绍到过连通域的概念,简单来说就是图像中一片颜色近似一致的区域,准确说是某一片区域中的任何一个像素都与该区域的其他的一个或几个像素8连通(或4连通),连通是指两个像素相邻并且某些属性相同(狭义上是灰度值,广义上可以像素所具备的各种属性,我看的论文里属性就是指像素所在笔画的笔画宽度),那么把这些相同的区域做上统一的标记是我们经常要做的事,研究这一类问题的算法我们就称其连通域标记算法,连通域标记是最基本的图像处理算法之一。
关于这一类问题,先说说我的想法。
想法一:
第一次了解这个问题的时候,看的是维基百科上关于这个的介绍,全英文嘛没看太懂,但是看懂了一部分,于是出现了我的第一种时间效率极其差的办法:
1.逐行扫描,对除了边界像素的每一个像素(边界像素特殊处理)作分析,分析它的左、左上、上、右上邻居:
(1)如果本像素的属性与其他四个邻居中每一个邻居的属性都不同(例如都不是一个灰度级别,再如笔画宽度不在同一个区间范围),那么区域号加1,并把这个新的区域号标记本像素的区域号;
(2)如果只和其中某一个邻居属性相同,那么把邻居的区域号标记本像素区域号
(3)如果和多个邻居属性相同,但是邻居的区域号又各有不同,那么说明了不同邻居虽然区域号不同,但是他们其实是在同一个连通域中,只不过没有扫描到本像素之前,他们并未汇合,所以这里就要统一他们的区域号,这里需要扫描所有的已经标记过的像素,把其中标记的区域号和本像素的邻居们区域号相同的那些像素群的区域号全部统一为其中最小的那个值,同时本像素标记也设为那个值。
2.重复1直到所有点全部扫描完成,最后可以得到一个大小和图像一样大的区域号map,区域号map的值是图像中对应位置的像素所在的区域号。
这样下来,经过一遍扫描之后,各个连通域的区域号已经设定出来,但是会出现不是区域号1,2,3,4,5。。。这样,而可能是1,3,4,6,9。。。这样。 时间复杂度上是O(n^2),n为图像像素的个数。
当然这种算法跑下来时间很久,一张640*480的图需要3分钟(当然是matlab我内部还有许多其他的判定和执行过程)。
想法二:
当然不能就此就这样了,我需要跑200多张图片,一张3分钟。。。所以得改进,重新看了维基百科和一部分介绍二值图像连通域标记算法的论文,发现原来他们讲的是扫描两遍的思想,于是借鉴了他们的想法:
1.还是从上至下逐行扫描,如果遇到想法一里面的(1)(2)两种情况,方法不变,如果遇到第三种情况,不像想法一中那样傻傻的再扫描一次统一赋值,而是把这些邻居的区域号码作为一个对记录到等价关系表equal中,equal(i)=【xi yi】表明区域号为xi,yi的区域是在同一片连通域中,并且在等价表中第i行。那么这里时间复杂度是O(n),
2.把等价关系表先简化,除去重复的部分,再从表做树形检索:
从表的equal(1)开始,在表中搜索满足x1∈equal(i)或者y1∈equal(i)的i的集合,再对集合中每一个i继续做检索直到表中和x1,y1有等价关系的区域号全部被找到。记录下这些区域号,把这些区域号对应的像素,全部统一,从表中删去这些对。重复对表做这样的树形检索,直到每一对都被扫描到,表最后为空,结束,这里的时间复杂度又是O(n),但是用到递归调用,会占据大量的空间,matlab跑竟然报out of memory= =。
想法三:
http://www.cnblogs.com/tiandsp/archive/2012/12/06/2804922.html
这个是网上看到的,同样是两步计算,大同小异,但是比传统的两步标记简单一些,不是等价对,而是等价序列,递归的过程更简单清楚,里面关于算法里面并查集 的介绍很好
想法四:
C:http://blog.stevenwang.name/connected-component-labeling-rg-545001.html
Matlab:http://www.cnblogs.com/tiandsp/archive/2012/12/06/2805276.html
同样是这位老兄推荐的别人的方法,区域生长法,简单高效,O(n)复杂度,实测很快
最后还是借鉴的想法四的思想,毕竟速度快,看来以后得多看一些算法方面的书了。