提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
在数字图像处理和计算机视觉领域,图像分割技术扮演着至关重要的角色。它将复杂的图像分解为若干具有相似特性的区域,为后续的图像理解、分析和应用奠定了基础,本博客将介绍图像分割领域中的一个分支:超像素图像分割。
一、超像素图像分割简介
超像素图像分割是计算机视觉领域的一项重要技术,它将图像细分为一系列具有相似特征的像素集合,这些集合被称为超像素。该方法旨在减少图像处理中的基本单元数量,同时保留关键的结构和纹理信息,从而提升图像处理和分析的效率和精确度。超像素的特点包括紧凑性、同质性和良好的边界保持能力,这使得图像分割过程更加高效和自然。
在具体实现上,流行的超像素分割算法包括SLIC、SEEDS和LSC等。SLIC算法结合颜色和空间信息,通过简单的线性迭代聚类过程,生成大小均匀的超像素。SEEDS算法采用能量驱动采样,通过迭代优化超像素边界,以适应图像的颜色和纹理变化。LSC算法则利用谱聚类技术,更加注重保持图像的细节和边缘信息。在
二:SLIC超像素图像分割
SLIC(Simple Linear Iterative Clustering)是一种用于图像分割的超像素生成算法。它通过简单的线性迭代聚类方法,将图像分割成具有相似特征的像素集合,即超像素。SLIC算法以其效率高、分割质量好、易于实现等特点,在计算机视觉领域得到了广泛应用。
SLIC算法的核心思想是将图像空间划分为多个小的区域,每个区域内的像素在颜色、亮度、纹理等方面具有相似性。以下是SLIC算法的基本步骤:
- 初始化聚类中心:在图像中均匀地选择初始聚类中心,通常根据期望的超像素数量来确定。
- 距离度量:对于每个聚类中心,算法在它的邻域内搜索像素,并计算像素与聚类中心之间的距离。这个距离是一个综合距离,包括颜色空间的距离和空间距离。
- 迭代优化:通过迭代优化过程,不断更新聚类中心和像素的归属,直到满足一定的收敛条件。
- 生成超像素:最终,每个聚类中心及其归属的像素形成了一个超像素。
在opencv中存在其实现api:cv2.ximgproc.createSuperpixelSLIC,参数说明:
image: 输入图像,应该是一个 3 通道的彩色图像(通常是 BGR 格式)。
region_size: 超像素区域的大小,即每个超像素的平均大小。这个值越大,生成的超像素数量越少,每个超像素覆盖的面积也越大。
ruler: 空间权重因子,用于平衡颜色相似性和空间接近性。这个值越大,超像素的形状越接近正方形。
一旦创建了 SuperpixelSLIC 对象,就可以使用以下方法来执行超像素分割和获取结果:
slic.iterate(num_iterations)
labels = slic.getLabels()
num_superpixels = slic.getNumberOfSuperpixels()
mask = slic.getLabelContourMask()
其中:iterate: 执行超像素分割的迭代过程,getLabels: 获取每个像素的超像素标签,getNumberOfSuperpixels: 获取生成的超像素的总数,getLabelContourMask: 获取超像素边界的掩码,可以用来在原图上绘制超像素边界。
示例代码:
import cv2
import numpy as np
# 读取图像
img = cv2.imread(r"D:\AI_tool\GFPGAN-master\1.jpg")
img = cv2.resize(img,(0,0),fx=0.5,fy=0.5)
# 初始化SLIC,设置超像素平均尺寸和平滑因子
slic = cv2.ximgproc.createSuperpixelSLIC(img, region_size=20, ruler=20.0)
# 迭代次数,越大效果越好
slic.iterate(10)
# 获取超像素标签和数量
labels = slic.getLabels()
number_of_superpixels = slic.getNumberOfSuperpixels()
# 获取超像素边缘Mask并绘制
mask = slic.getLabelContourMask()
img_slic = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("img_slic",img_slic)
cv2.waitKey(0)
效果:
三:Seed超像素分割算法
Seed超像素图像分割算法是一种基于图论的超像素生成方法,它通过在图像中播种(seed)并生长(grow)超像素来达到分割的目的。Seed超像素算法的核心思想是利用像素之间的相似性,将相似的像素聚集成一个超像素。
算法步骤:
- 种子点初始化: 在图像中随机或均匀地选择一些像素作为种子点(seed points)。 每个种子点代表一个潜在的超像素中心。
- 相似性度量: 计算每个种子点与其邻域像素之间的相似性,通常使用颜色、亮度、纹理等特征。 相似性度量可以基于欧几里得距离或其他距离度量。
- 种子点生长: 根据相似性度量,将每个种子点与其最相似的邻域像素合并,形成超像素。
生长过程中,需要确保每个超像素的大小在一定范围内,并且形状尽可能规则。 - 迭代优化: 重复相似性度量和种子点生长步骤,直到满足一定的停止条件,如达到预设的超像素数量或大小。
- 后处理: 对生成的超像素进行后处理,如合并过小的超像素,或者调整超像素边界以优化分割结果。
在opencv中提供了Seed的api,cv2.ximgproc.createSuperpixelSEEDS( image_width, image_height, image_channels, num_superpixels, num_levels, prior, num_histogram_bins)
参数说明:
image_width: 输入图像的宽度。
image_height: 输入图像的高度。
image_channels: 输入图像的通道数(例如,对于彩色图像通常是 3)。
num_superpixels: 指定生成的超像素的数量。这个参数对最终的分割结果有直接影响。
num_levels: 指定金字塔的层数。这个参数影响算法的迭代次数和超像素的最终大小。
prior: 指定超像素形状的先验知识。较高的值会产生更规则的超像素形状。
num_histogram_bins: 直方图分箱的数量。用于计算像素之间的相似度,较高的值可以提高算法对图像中颜色变化的敏感度。
使用代码:
import cv2
import numpy as np
# 读取图像
img = cv2.imread(r"D:\AI_tool\GFPGAN-master\1.jpg")
img = cv2.resize(img,(0,0),fx=0.5,fy=0.5)
# 初始化SLIC,设置超像素平均尺寸和平滑因子
seeds = cv2.ximgproc.createSuperpixelSEEDS(img.shape[1], img.shape[0], img.shape[2], 300, 5)
# 应用超像素分割
seeds.iterate(img, 10) # 迭代次数,可以根据需要调整
# 获取超像素标签
labels = seeds.getLabels()
# 获取超像素数量
num_superpixels = seeds.getNumberOfSuperpixels()
# 在原图上绘制超像素边界
mask = seeds.getLabelContourMask()
img_out = cv2.bitwise_and(img, img, mask=mask)
# 显示结果
cv2.imshow('Superpixels', img_out)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果:
四 :LSC超像素分割
LSC超像素分割算法的核心思想是将图像像素看作图中的节点,像素之间的相似性通过边的权重来表示。然后,算法在图上执行谱聚类(Spectral Clustering)来形成超像素。
主要步骤:
- 构建图: 将图像像素映射为图中的节点。 计算像素之间的相似性度量(如颜色、亮度、纹理等),这些度量作为图中边的权重。
- 定义权重矩阵: 根据像素间的相似性,构建一个权重矩阵W,其中W[i, j]表示像素i和像素j之间的权重。
- 构造拉普拉斯矩阵: 使用权重矩阵W构造图的标准拉普拉斯矩阵L = D - W,其中D是对角矩阵,D[i, i]是W中第i行的权重之和。
- 特征分解: 对拉普拉斯矩阵L进行特征分解,找到最小的几个特征值对应的特征向量。
- 聚类: 将这些特征向量组成的矩阵进行k-means聚类,其中k是预定的超像素数量
聚类结果将图像像素划分为k个超像素。 - 优化边界: 为了得到更紧凑的超像素,LSC算法可能会包含一个优化步骤,通过最小化边界像素的权重和来调整超像素的边界。
在opencv中提供了其使用api:superpixel = cv2.ximgproc.createSuperpixelLSC(image, region_size, ratio)
参数说明:
image: 输入图像,它应该是一个8位的3通道图像(通常是彩色图像)。
region_size: 指定超像素区域的大小。这个参数决定了超像素的粗细程度,值越大,生成的超像素数量越少,每个超像素的大小也越大。
ratio: 控制超像素紧凑性的参数。这个参数通常是一个大于0且小于1的值,它影响了超像素之间的边界平滑程度。值越大,超像素越紧凑。
使用代码:
import cv2
import numpy as np
# 读取图像
img = cv2.imread(r"D:\AI_tool\GFPGAN-master\1.jpg")
img = cv2.resize(img,(0,0),fx=0.5,fy=0.5)
# 初始化SLIC,设置超像素平均尺寸和平滑因子
# 创建 LSC 分割器
region_size = 50 # 超像素区域大小
min_element_size = 200 # 最小元素大小
# 创建 LSC 超像素分割器
lsc = cv2.ximgproc.createSuperpixelLSC(img, region_size)
# 运行超像素分割
lsc.iterate(10) # 迭代次数
# 获取分割结果
num_superpixels = lsc.getNumberOfSuperpixels()
labels = lsc.getLabels()
# 可视化分割结果
labels = np.uint8(labels)
segmented_image = cv2.cvtColor(labels, cv2.COLOR_GRAY2BGR)
segmented_image = cv2.applyColorMap(segmented_image, cv2.COLORMAP_JET)
# 将超像素边界绘制在原始图像上
mask = lsc.getLabelContourMask()
img_lsc = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow('LSC Superpixel Segmentation', img_lsc)
cv2.waitKey(0)
cv2.destroyAllWindows()