最近要考试了,所以现在不写,怕这段时间都没空写了。(算法的效率暂时不考虑,有时间了再来解决彩色信息和效率问题)
继上一篇的算法:http://blog.csdn.net/abcd_d_/article/details/41218549,本文对分水岭算法进行了区域合并,合并准则采用hsv颜色空间的区域特征的直方图相似度进行合并。且看效果:图一是原图,图二是采用之前的文章算法的效果,图三为进行了区域合并后的效果。(大小被我调整过)
(图一)
(图二)
(图三)
在第一篇的基础之上,增加了区域合并算法,也就是下图中划横线的两个关键方法。可以从上图中看出,区域合并能有效去除过分割问题。
第一个方法相对简单,遍历图像找出领域关系,并存储在hashMap的一个对象nodes中。关键在第二个方法arearCombine(),它需要遍历nodes中的区域,并根据合并准则(这里是面积大小和区域相似度),判断是否把该区域合并到合适的领域中,这样两个区域就变为一个新区域。(这里涉及到邻接图的合并) 这样一遍一遍下来,直到没有区域被合并为止。
问题看似简单,但是问题来了,就是nodes这个数据结构每一次遍历后都会被修改,因此涉及到hashMap等集合不同在遍历的同时,又对其进行修改的问题。本文的方法比较笨,就是采用先记录下要修改的信息,然后在遍历完成之后再进行修改(这个麻烦,有更好的方法的朋友,请不吝赐教^_^)。
最后说明一下,本文要根据区域特征进行合并,所以添加了一个辅助类Img_Area_Feature ,该类记录下区域特征,并且进行区域的一些合并或者添加像素点操作。另外,文章的区域合并算法的关键在于合并准则的选择,修改size(面积)、similarity(相似度)的判断标准则,以及修改相似的判断方法均对效果产生直接影响,这也是这个合并算法的不足之处。
/** * ///此处的合并准则直接影响合并效果!!!!!!!!!!!!!!!!!!!! */ if(size<30){ ////少于10个像素,则合并到其中一个临域中 simMap.put(similarity, child.getKey()); }else if(similarity<0.1&&similarity!=-1&&size<500){ ///大于10个像素,则根据与临域的饱和度差和色调差选择性合并 simMap.put(similarity, child.getKey()); }else if(similarity<0.2&&similarity!=-1&&size<200){ ///大于10个像素,则根据与临域的饱和度差和色调差选择性合并 simMap.put(similarity, child.getKey()); }
例如,将上面的判断条件size<30改为size<100则效果如下图(图四),可以发现效果变化很明显:
:
(图四)
最后附上代码地址:http://download.csdn.net/detail/abcd_d_/8223951 (要一个积分:最近要下载,积分紧张,所以。。。)