六、 图像分割
6.1阈值分割
6.1.1阙值分割的基本概念
根据图像的灰度值来对图像进行分割,高于灰度值的常被认为是前景图像,而低于灰度值的则被认为是背景图像。阙值的设定并不是唯一的,在对灰度图像进行阙值分割时可以设置多个阙值。
6.1.2全局阙值与局部阙值
**全局阙值:**对图片中所有像素都适用的阙值。
**局部阙值:**图片中某像素的阙值是根据其的邻接像素等计算得出,该阙值只作用与某一部分素值。
6.1.3灰度直方图与阙值的关系
**双峰直方图:**对于双峰图像,其的两个峰顶往往代表像素集中的两个区域,可以理解成是目标和背景,在双峰图像中常常选用双峰间波谷处的灰度值作为阙值,因为波谷处的深度相对较大,这就代表其的像素数量远远少于波峰处的像素数量,即目标和背景存在显著差异。(注:此处的灰度值并不是波谷小于波峰),通常波谷越宽越深越有利于图像进行阙值分割。
|-----|--------|----------|----------|
| | 波峰 | 波谷 | 波峰 |
| 灰度值 | 0~150 | 150~200 | 200~255 |
**单峰直方图:**当灰度直方图为单峰形状时,阈值的选择比较复杂。可能需要通过图像的其他统计特性(如均值、方差等)或使用复杂的阈值确定方法(如迭代法、最大熵法等)来确定阙值。
6.1.4Otsu方法确定图像阙值
在实际应用中,常常使用自动选择阙值的仿佛,比如Otsu方法(最大类间方差法)是一种在图像处理中广泛使用的自动阈值选择技术。其的主要步骤如下:
1.计算图像的灰度直方图:
计算图像的灰度直方图,即统计图像中每个灰度级出现的次数。
2.计算图像的总像素数、平均灰度等 :
设图像的总像素数为N,灰度级范围为[0, L-1],其中L是灰度级的数量(对于最常见的(uint8)类型的图像,L的最大取值通常是256);计算图像的平均灰度值μ。
3.遍历所有可能的阈值 :
对于灰度级范围[0, L-1]内的每一个值t,将其作为阈值,然后将图像分割成两部分:①灰度级在[0, t]的像素作为背景,②灰度级在[t+1, L-1]的像素作为前景。
4.计算前景和背景的像素数及平均灰度 :
对于每个阈值t,计算前景和背景的像素数(分别记为N0和N1),以及前景和背景的平均灰度(分别记为μ0和μ1)。
5.计算类间方差 :
σ² = w0 * (μ0 - μ)² + w1 * (μ1 - μ)²
其中,w0和w1分别是背景和前景的像素数占总像素数的比例(即w0 = N0 / N,w1 = N1 / N)。
6.择最大类间方差对应的阈值 :
遍历完所有可能的阈值后,选择使方差σ²最大的阈值作为最佳阈值。
7.应用阈值进行分割 :
使用找到的最佳阈值将图像分割成前景和背景两部分。
python
import cv2
import numpy as np
# 读取图像
image = cv2.imread('fu.jpg', 0) # 第二个参数0表示以灰度模式读取图像
# 使用Otsu方法进行阈值分割
ret, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 将两张图片缩小一半
resized_image = cv2.resize(image, (0, 0), fx=0.5, fy=0.5)
resized_thresh = cv2.resize(thresh, (0, 0), fx=0.5, fy=0.5)
# 将两张缩小后的图片水平堆叠
combined_image = np.hstack((resized_image, resized_thresh))
# 显示合并后的图像
cv2.imshow('Combined Image', combined_image)
# 等待按键操作后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
ret, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
对输入的灰度图像
image
进行二值化操作,并使用Otsu方法自动确定最佳的阈值。操作后,它会得到两个值:ret
是计算得出的最佳阈值,thresh
是阈值分割后的二值化图像,其中像素值只有0和255,分别代表黑色和白色。cv2.THRESH_BINARY:表示对图像进行二值化操作。
cv2.THRESH_OTSU
:表示使用Otsu方法来自动确定最佳阈值。
6.1.5自适应图像分割
自适应图像分割能够通过分析图像的不同区域特性(比如亮度、对比度、纹理等),动态的计算每一部分的分割阙值。这种方法能够适应图像内容的多样性,从而提高分割的准确性和鲁棒性。
python
import cv2
import numpy as np
# 读取图像
image = cv2.imread('fu.jpg', 0) # 第二个参数0表示以灰度模式读取图像
# 使用自适应阈值进行图像分割
adaptive_thresh = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 2)
# 将两张图片缩小一半
resized_image = cv2.resize(image, (0, 0), fx=0.5, fy=0.5)
resized_adaptive_thresh = cv2.resize(adaptive_thresh, (0, 0), fx=0.5, fy=0.5)
# 将两张缩小后的图片水平堆叠
combined_image = np.hstack((resized_image, resized_adaptive_thresh))
# 显示合并后的图像
cv2.imshow('Combined Image', combined_image)
# 等待按键操作后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
使用自适应阈值进行图像分割
adaptive_thresh = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 2) 必须是奇数
这行代码使用了OpenCV库中的**
cv2.adaptiveThreshold
**函数来进行自适应阈值图像分割。它接收一个灰度图像,并输出一个二值化后的图像。在二值化操作中,超过阈值的像素会被设置为最大值255,否则设置为0。这个阈值是动态计算的,基于每个像素周围9x9区域内的平均值减去一个常数2(也就是代码最后设置的两个参数)。这种自适应阈值算法能够根据图像的不同区域特性自动调整分割参数,实现更准确的图像分割。
注:本人为在校学生,博客是边学边写的,主要是为了巩固知识,如有错误请积极指正。
本文的内容主要基于我对张运楚教授编著的《数字图像处理》一书的学习和理解。这本书深入浅出地介绍了数字图像处理的基本理论以及经典算法等,并且提供了丰富的示例代码和实际用例,极大地帮助了我学习图像处理知识。在此,我推荐大家阅读这本书,更加深入的学习有关图像处理的知识