一、图像分割

图像分割就是将图像分为一些有意义的区域,然后可以对这些区域进行描述,相当于提取出某些目标区域的特征。图像分割的基础是像素间的相似性和跳变性

通常,我们对图像进行分割,分割的小区域是某种意义下具有共同属性的像素的连通集合。各区域类某种性质,如灰度、纹理有相似性。区域内部是连通,无过多小孔。并且有明显边界。

图像分割的四种不同的基本方法

  1. 边缘检测:检测出边缘,再将边缘像素连接,构成边界形成分割。找出目标物理的轮廓,进行目标的分析、识别、测量
  2. 阈值分割:最常用法。有直方图门限选择,半阈值选择图像分割,迭代阈值。
  3. 边界方法:直接确定取余边界,实现分割;有边界跟踪法,轮廓提取法。
  4. 区域法:将各个像素划归到相应物体或者区域的像素聚类法

图像的阈值分割

有以下三种基本方法

  • 直方图门限选择
  • 半阈值选择图像分割
  • 迭代阈值图像分割

第一种直方图门限选择确定阈值T的原理主要是根据,物理的背景和前景往往是不通,体现在直方图上的化就是其灰度值成明显的双峰值。

例:下面有一幅图

envi 深度学习 分割_阈值分割


其对应的,灰度级直方图如下:

envi 深度学习 分割_opencv_02


我们可以很清晰的看到,波谷大概位于215处为止。现在我们对此进行阈值分割,其效果如下

envi 深度学习 分割_图像分割_03


那么,我们怎么选择对应的波谷呢?如果有多个波谷、波峰该怎么办呢?

最简单粗暴的就是通过人工来填写阈值。当然这种方法也就违背了我们做图像识别的意义了。

如果有多个波谷,那么我们选择多个阈值即可。其数学表达式大概如下

envi 深度学习 分割_计算机视觉_04

半阈值选择分割法
该方法原理就是,不论图像的直方图具有双峰还是多峰,阈值化之后原多值图像都将会变成二值图像。如果希望只将图像的背景变成二值图像,而物理任然为多值图像,此时,我们可以采用半阈值分割法

envi 深度学习 分割_计算机视觉_05


半阈值分割法的效果图如下

envi 深度学习 分割_envi 深度学习 分割_06

迭代阈值分割法

迭代阈值分割法是一种自动算出阈值的,不需要人工参与的。

其基本思想,选择一个阈值作为初值,按照某种策略,直到满足某种条件,跳出循环,输出阈值。

envi 深度学习 分割_opencv_07


用代码实现,即如下

# 自动迭代阈值法
    def  GetThresholdvalue(self):
        # 辅助函数,得到图像的统计数据
        def helper1():
            static = np.array([0 for i in range(0, 256)])
            s = np.array([])
            for y in range(0,len(self.Img)):
                for x in range(0,len(self.Img[y])):
                    Col=self.Img[y][x][0]
                    static[Col]=static[Col]+1
            return static
        # 下面几步是用来确定初始化阈值的
        def helper2(arr,pos):
            sum=0
            c=0
            for i in  range(0,len(arr)):
                sum=sum+arr[i]*(i+pos)
                c = c + arr[i]
            if c==0:
                return 0
            return int(sum/c)
        tv = helper1() #得到图像的统计数据
        c_init=helper2(tv,0) # 计算出平均灰度值,作为初始阈值
        # 下面开始迭代
        l_tv=tv[:c_init]
        r_tv=tv[c_init:]
        lastavg=c_init
        while True:
            L_avg=helper2(l_tv,pos=0)
            R_avg=helper2(r_tv,pos=lastavg)
            avg=int((L_avg+R_avg)/2)
            if np.abs(avg-lastavg)<2:
                break
            l_tv = tv[:avg]
            r_tv = tv[avg:]
            lastavg=avg
        return lastavg