图像处理
Author:louwill
Machine Learning Lab
基于阈值的图像分割,由于其处理直观、实现简单、计算速度快,是更常见的传统图像分割算法。 本文基于图像灰度阈值处理的基本原理,介绍全局阈值处理方法和xhdfk,并使用几个图像示例进行说明。
基于灰度阈值给出灰度图像,假设该图像中有对象物体和背景像素,从图像中提取对象物体的最直接的方法之一是使用固定的阈值分离对象物体像素和背景像素,将区域作为对象物体区域,否则作为背景区域。
那么什么样的图像更容易用阈值法分割呢? 简单来说,如果目标区域和背景区域之间存在较大的图像灰度差,用阈值法进行分割可能会更有效。 当图像直方图中出现这样大的图像灰度差异时,出现图像灰度直方图的双峰特征。 如图1所示。
图1双峰图像直方图
要通过阈值分割方法获得良好的分割效果,需要依赖于以下关键因素:
直方图峰值之间的间隔
图像噪声状况
目标物体和背景的相对尺寸
图像光源均匀性;
图像反射的均匀性。
全局阈值处理在图像有较大灰度变化时,使用全局阈值处理的方法通常会取得较好的效果。 但是对于一个图像,我们希望找到比较合理的阈值作为全局阈值。 因此,有一种迭代的阈值图像分割算法。 算法流程如下。
初始化全局阈值
通过分割该图像,生成由灰度值大像素构成、灰度值为以下的像素构成的两组像素
对每个像素计算平均灰度值和
计算新的阈值
重复步骤2到4,直到连续迭代的值之间的差值小于给定参数。
让我们来看一个使用全局阈值的图像分割示例。 直接读取图像,首先根据Numpy进行灰度化和二值化处理。
img=cv2.imread(‘./Harden.png ‘ )灰度化y=0.2126*img ) :2 ) 0.7152*img ) :1 ) 0.0760 1 2 ]=以y # 128为阈值二值化y [ y=128 ]=255 y [ y128 ]=0img [ :0 ]=yimg [ :3360,0 ]=yimg [ 3360,]
图2原图
图3全局阈值分割效果图
opencv还提供了划分全局阈值的方法。 处理代码如下。
import c v2 importnumpyasnpfrommatplotlibimportpyplotaspltimg=cv2.im read (‘ harden.png ‘,0 ) img=cv2.cvtcolor(img分割
xt-align:center;”>图4 opencv阈值法分割
xhdfk(OTSU)
基于阈值的图像二值化方法的一个关键在于如何选定阈值,这可以视作为一个全局寻优问题。xhdfk也即OTSU法,是由日本学者大津展之于1979年提出的一种图像阈值分割方法。该方法将阈值划分视作是一个统计决策问题,其目的在于将像素分配给两组或多组的过程中使得引入的平均误差最小。xhdfk给出的方案是使得两组之间的类间方差最大时的阈值为最优阈值。所以xhdfk也叫最大类间方差法。
先来看一下xhdfk的基本原理。假设划分阈值为,小于阈值的像素区域为,大于阈值的像素区域为。和分别为被阈值分开的两类像素占总像素的比值。和分别为这两个类像素均值,和分别为这两个类中像素值的方差。
图像的类内方差和类间方差为:
图像的整体方差为:
图像的可分离度定义为:
最大化图像分离度即可,所以使得:
最大化即可。
基于NumPy的xhdfk实现例子如下代码所示。
img = cv2.imread(‘./harden.png’)img = img.astype(np.float)H, W, C = img.shape# 灰度化out = 0.2126*img[:,:,2] + 0.7152*img[:,:,1] + 0.0722*img[:,:,0]out = out.astype(np.uint8)# 初始化类间方差和最佳阈值max_sigma = 0max_t = 0# 遍历迭代for _t in range(1, 255): # 小于阈值t的类v0 v0 = out[np.where(out<_t)] # 计算v0均值 M0 = np.mean(v0) if len(v0) > 0 else 0. # v0类像素占比 w0 = len(v0)/(H*W) # 大于阈值t的类v1 v1 = out[np.where(out>=_t)] # 计算v1均值 M1 = np.mean(v1) if len(v1) > 0 else 0. # v1类像素占比 w1 = len(v1)/(H*W) # 类间方差 Sb2 = w0*w1*((M0-M1)**2) # 寻优 if Sb2 > max_sigma: max_sigma = Sb2 max_t = _t # 打印最佳阈值 print(max_t)
通过xhdfk寻优可知示例图片的最佳划分阈值为。然后以为阈值进行二值化。效果如图5所示。
图5 xhdfk阈值分割
opencv中直接提供了xhdfk的实现方法,如下代码所示。
img = cv2.imread(‘./harden.png’)# 灰度化img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# xhdfk阈值化处理ret, th = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)plt.imshow(th); 小结
本文对基于阈值的图像分割方法进行了简单的介绍,并给出了相应的图像实例。基于阈值的图像分割方法简单直接,计算速度快,在图像灰度差异较大的情况下,是首选的分割方法。但阈值分割方法本身也存在抗噪能力弱、使用条件严格等缺点,所以往往会配合图像滤波去噪等方法一起使用。
参考资料
[1] 数字图像处理第四版
[2] https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html
往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑AI基础下载辛勤的山水老师《机器学习课程》视频课辛勤的山水老师《机器学习课程》711页完整版课件
本站qq群851320808,加入微信群请扫码: