数字图像处理5之图像分割

1. 概念

把图像划分成若干个特定的、具有独特性质的区域,并提取其中感兴趣目标的基数和过程。它是由图像处理到图像分析的关键步骤。现有的图像分割方法主要分以下几类:基于阈值的分割方法、基于区域的分割方法、基于边缘的分割方法以及基于特定理论的分割方法等。从数学角度来看,图像分割是将数字图像划分成互不相交的区域的过程。图像分割的过程也是一个标记过程,即把属于同一区域的像素赋予相同的编号。

1998年以来,人工神经网络识别技术已经引起了广泛的关注,并且应用于图像分割。基于神经网络的分割方法的基本思想是通过训练多层感知机来得到线性决策函数,然后用决策函数对像素进行分类来达到分割的目的。这种方法需要大量的训练数据。神经网络存在巨量的连接,容易引入空间信息,能较好地解决图像中的噪声和不均匀问题。选择何种网络结构是这种方法要解决的主要问题。

2. 阈值分割

灰度阈值分割法是一种最常用的并行区域技术,它是图像分割中应用数量最多的一类。阈值分割方法实际上是输入图像f到输出图像g的如下变换:
g ( x , y ) = { 1 , f ( x , y ) > T 0 , f ( x , y ) ≤ T g(x,y)= \begin{cases} 1, & \text {$f(x,y)>T$} \\ 0, & \text{$f(x,y)\leq T$} \end{cases} g(x,y)={ 1,0,f(x,y)>Tf(x,y)T
其中,T为阈值,f(x,y)为点(x,y)的像素值,g(x,y)为分割后的图像。

阈值分割算法的关键是确定阈值,如果能确定一个合适的阈值就可准确地将图像分割开来。阈值确定后,将阈值与像素点的灰度值逐个进行比较,而且像素分割可对各像素并行地进行,分割的结果直接给出图像区域。

阈值包括全局阈值、自适应阈值、最佳阈值等等。

2.1 全局阈值

全局阈值是指整幅图像使用同一个阈值做分割处理,适用于背景和前景有明显对比的图像。它是根据整幅图像确定的:T=T(f)。但是这种方法只考虑像素本身的灰度值,一般不考虑空间特征,因而对噪声很敏感。常用的全局阈值选取方法有利用图像灰度直方图的峰谷法、最小误差法、最大类间方差法、最大熵自动阈值法以及其它一些方法。

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('coin.png',0)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in xrange(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

在这里插入图片描述

2.2 自适应阈值

对于光照不均的图像,全局阈值方法显得苍白无力。自适应阈值应运而生,就是根据桐乡不同区域的亮度分布不同,计算其局部的阈值。通过计算某个邻域(局部)的均值、中值、高斯加权平均(高斯滤波)来确定阈值。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('sudoku.png',0)
img = cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
th2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,\
            cv.THRESH_BINARY,11,2)
th3 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv.THRESH_BINARY,11,2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
            'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

在这里插入图片描述
在这里插入图片描述

扫描二维码关注公众号,回复: 13500002 查看本文章

2.3 最佳阈值(Otsu)

最佳阈值方法,称之为Otsu算法,即最大类间方差法。下面给出求类间方差原理:
约定如下

  • L个不同灰度级{0,1,2,…,L-1}
  • 数字图像M*N像素
  • n i n_{i} ni是灰度级为i的像素数; M N = n 0 + n 1 + . . . + n L − 1 MN=n_{0}+n_{1}+...+n_{L-1} MN=n0+n1+...+nL1
  • 灰度级i出现的概率 p i = n i / M N p_{i}=n_{i}/MN pi=ni/MN

假设图像中的像素按照灰度级用阈值t划分为两类:背景类 C 0 C_{0} C0和目标类 C 1 C_{1} C1;背景类 C 0 C_{0} C0的灰度级为0~t;
目标类 C 1 C_{1} C1的灰度级为t+1~L-1。

两类出现的概率,分别为:
P 0 ( t ) = ∑ i = 0 t p i P 1 ( t ) = ∑ i = t + 1 L − 1 p i P_{0}(t)=\sum_{i=0}^t p_{i} \\ P_{1}(t)=\sum_{i=t+1}^{L-1} p_{i} P0(t)=i=0tpiP1(t)=i=t+1L1pi

两类的平均灰度值分别为(推导参见下方):
m 0 ( t ) = 1 P 0 ( t ) ∑ i = 0 t i p i m 1 ( t ) = 1 P 1 ( t ) ∑ i = t + 1 L − 1 i p i m_{0}(t) =\frac{1}{P_{0}(t)}\sum_{i=0}^{t} ip_{i} \\ m_{1}(t) =\frac{1}{P_{1}(t)}\sum_{i=t+1}^{L-1} ip_{i} m0(t)=P0(t)1i=0tipim1(t)=P1(t)1i=t+1L1ipi

图像的总平均灰度值为:
m = ∑ i = 0 L − 1 i p i m = \sum_{i=0}^{L-1} ip_{i} m=i=0L1ipi

图像中两类的类间方差为:
δ 2 ( t ) = P 0 ( m − m 0 ) 2 + P 1 ( m − m 1 ) 2 \delta^2(t) = P_{0}(m-m_{0})^2 + P_{1}(m-m_{1})^2 δ2(t)=P0(mm0)2+P1(mm1)2
定义域 t ∈ [ 0 , L − 1 ] t\in[0,L-1] t[0,L1] δ 2 ( t ) \delta^2(t) δ2(t)最大值时的t值,就是要求的最优阈值。

备注:
两类平均灰度值的推导

m 0 ( t ) = ∑ i = 0 t i P ( i ∣ C 0 ) = ∑ i = 0 t i P ( C 0 ∣ i ) P ( i ) P ( C 0 ) = ∑ i = 0 t i p ( i ) P 0 ( t ) m_{0}(t) = \sum_{i=0}^{t} iP(i|C_{0}) \\ = \sum_{i=0}^{t} i \frac{P(C_{0}|i)P(i)}{P(C_{0})} \\ = \sum_{i=0}^{t} i \frac{p(i)}{P_{0}(t)} \\ m0(t)=i=0tiP(iC0)=i=0tiP(C0)P(C0i)P(i)=i=0tiP0(t)p(i)
其中: P ( C 0 ∣ i ) = 1 P(C_{0}|i) = 1 P(C0i)=1 P ( C 0 ) P(C_{0}) P(C0)正是 C 0 C_{0} C0出现的概率 P 0 ( t ) P_{0}(t) P0(t)

3. 区域分割

3.1 区域生长法

  • 介绍

区域生长法,是基于区域的图像分割方法。该算法从“种子”开始,即选取一个或一组像素点作为算法的起点,从种子出发判断邻近点是否满足算法定义的相似性准则。若满足则将邻近点归入同一区域,并将其作为新的种子重新“生长”,直至不再有新的点归入区域,算法分割结束。算法定义的相似性准则需要根据具体的情况而定,通常是根据图像的灰度值、矩、纹理等。

  • 应用场景

没有先验知识可以利用时,可以取得最佳的性能,可以用来分割比较复杂的图像。

  • 缺点

空间和时间开销都比较大;通常会造成过度分割。

3.2 分水岭分割

分水岭分割,其思想是,将一幅图像看成一个地形图,灰度值对应地形的高度,高灰度值对应于山峰,低灰度值对应于山谷。水朝地势低的地方流动,直到局部低洼处,即盆地。最终所有的水都处于不同的盆地,盆地之间的山脊成为分水岭

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('coins.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)

# noise removal
kernel = np.ones((3,3),np.uint8)
opening = cv.morphologyEx(thresh,cv.MORPH_OPEN,kernel, iterations = 2)
# sure background area
sure_bg = cv.dilate(opening,kernel,iterations=3)
# Finding sure foreground area
dist_transform = cv.distanceTransform(opening,cv.DIST_L2,5)
ret, sure_fg = cv.threshold(dist_transform,0.7*dist_transform.max(),255,0)
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg,sure_fg)

# Marker labelling
ret, markers = cv.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers+1
# Now, mark the region of unknown with zero
markers[unknown==255] = 0

markers = cv.watershed(img,markers)
img[markers == -1] = [255,0,0]

plt.imshow(img)
plt.show()

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/duanyuwangyuyan/article/details/120168879