图像分割是视觉图像处理的基础,指的是将数字图像细分为多个图像子区域。这样方便对图像中的每个子区域进行特征统计,或者提取感兴趣的区域。
最简单的分割算法当属阈值分割,即在0到255之间设定一个值,当图像的灰度值大于等于的设定的值时为1,小于设定的值时为0.基于这种固定阈值分割算法又演变出多种阈值分割算法。如局部自适应阈值分割,动态阈值分割,基于局部均值和方法的阈值分割,利用直方图的波峰波谷特性进行阈值分割,最大类间方差分割等等阈值分割算法。这些分割算法都可以归为阈值分割算法。阈值分割的问题主要在于如何设定合适的阈值,对于背景和特征比较明显的图像,阈值分割比较有效,而且运行速度快,在机器视觉中是常用的方法。
除了阈值分割之外,还有一种分割算法是基于边界的分割。首先利用边界检测算法检测图像的边界,然后基于检测的边界对图像再进行阈值分割。如sobel算法,canny算法,LOG(高斯拉普拉斯算法),DOG(高斯差分算法)等等。边界检测算法主要是利用图像在边界位置的梯度变化来实现的。由于图像的边缘部分的梯度变化比较大,一般用一阶差分或二阶差分将边界凸显出来,然后进行阈值分割。这种分割算法比较依赖边界检测的准确性,但是梯度的变化即使在边界比较模糊的情况下也能够准确的检测出来,只要图像在边缘的灰度有一定的变化就可以,这是相对于阈值分割的有优点。但是边界检测算法有很多,如何选择合适的边缘检测算子也要根据不同的图像进行测试才能够得到更好的结果。
除了以上两种常见的分割算法之外,要有一种比较常用的分割算法,即基于区域的分割,如区域生长算法,分水岭算法,和最大稳定极值区域算法。
区域生长算法的基本思想是将有相似性质的像素点合并到一起。对每一个区域要先指定一个种子点作为生长的起点,然后将种子点周围领域的像素点和种子点进行对比,将具有相似性质的点合并起来继续向外生长,直到没有满足条件的像素被包括进来为止。这样一个区域的生长就完成了。图1是区域生长算法的示例。
算法实现步骤:
1)根据图像的不同应用选择一个或一组种子,它或者是最亮或最暗的点,或者是位于点簇中心的点;
2)选择一个描述符(条件);
3)从该种子开始向外扩张,首先把种子像素加入结果集合,然后不断将与集合中各个像素连通、且满足描述符的像素加入集合
4)上一过程进行到不再有满足条件的新结点加入集合为止。
图1 区域生长算法示例
区域生长算法需要手动这只种子点,这对机器视觉的应用是非常不利的。因此,在实际应用中。一般自动选择设定的一个局部区域内的均值或者中心像素点作为种子点,这样避免了手动选择的缺陷。常用的区域生长的判断生长条件一般采用灰度值的大小,即比较每个点与种子点的灰度值大小是否在一个范围内来确定是否生长。其实,这里还可以有别的生长条件,比如,利用梯度关系来判断是否生长这应该是一种比较稳定的生长条件。比如LSD直线检测算法其实就利用的梯度方向信息进行生长得到了比较好的效果。所以,利用区域生长算法的关键是如何设定生长的条件,如果找到一种好的条件,则分割出来的效果是非常好的。这也是目前部分人的研究方向。
分水岭算法是另一种比较有名的算法。按照百度百科上的说明,水岭算法有好多种实现算法。分水岭分割方法是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形成分水岭。分水岭的概念和形成可以通过模拟浸入过程来说明。在每一个局部极小值表面,刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,在两个集水盆汇合处构筑大坝,即形成分水岭。
分水岭算法的关键是找到局部区域的最小极值点,通常分水岭算法也不用灰度值大小,采用梯度大小来进行判断是一种比较稳健的方式。采用分水岭算法要防止过分割的问题。同样,分水岭算法也需要手工设置标志点。当然也可以通过计算的方式设置标志点。分水岭算法的步骤如下:
1)构建图像梯度图像。
2)通过一定规则生成n个最初的注水区域(先验知识或局部梯度最小值)。
3)往注水区域内加水,当两注水区域即将合并时,记录下此时的边界。
4)当图像边缘彻底被分割成n个独立区域是算法结束。
由于图像可能受到噪声的感染,因此,采用分水岭算法之前,一般先对图像进行平滑滤波处理。
MSER(最大稳定极值区域算法)是另一种分割算法,参考网上的介绍,是对一幅图像取阈值进行二值化处理,阈值从0到255依次递增。该算法类似于分水岭算法。在得到的所有二值图像中,图像中的某些连通区域变化很小,甚至没有变化,则该区域就被称为最大稳定极区域。MSER检测一次后需要将其反转,再做一次MSER检测,两次操作又称MSER+和MSER-。MSER主要用于自然场景的文本分割。
下面利用halcon来简单实现下这三种算法,利用的图像选自halcon自带的一张图像,比较下这三种算法的分割结果。
read_image(Image,'e:/test/work_sheet_02.png')
regiongrowing(Image,Regions, 5, 5, 16, 100)
gauss_filter(Image,ImageGauss, 5)
regiongrowing(ImageGauss,Regions1, 5, 5, 16, 100)
sobel_amp(ImageGauss,EdgeAmplitude, 'sum_abs', 3)
regiongrowing(EdgeAmplitude,Regions2, 5, 5, 16, 100)
watersheds_threshold(EdgeAmplitude,Basins, 15)
segment_image_mser(ImageGauss,MSERDark,MSERLight, 'both', 10, [], 15, [], [])
图2 图像分割结果比较
以上是这三种不同分割算法对同一图像的分割结果,分水岭算法没有对原图进行分割,而是采用了sobel操作之后进行分割,因为原图分割的效果实在太差了。大家可以采用不同的图像利用这三种算法进行分割,通过调整参数比较分割结果。从而找出最适合自己图像的分割算法。MSER应该是比较好的一种分割算法,尤其在自然场景文本检测方面的应用还是比较好的。当然,除了这几种分割算法,还有其他很多比较好的分割算法,比如利用机器学习的分割算法,这将在以后进行介绍。