一、Mean Shift 图像分割原理总结
Mean Shift 是一种基于密度梯度上升的无监督聚类算法,核心思想是通过迭代将每个像素点移动到局部密度极大值点(吸引子),从而实现图像分割。具体步骤包括:
- 核函数与带宽:利用核函数(如高斯核)定义局部区域,带宽决定邻域范围,平衡空间和颜色相似性。
- Mean Shift 向量计算:通过加权平均计算当前点的漂移方向,指向密度增加的区域。
- 迭代收敛:像素点沿 Mean Shift 向量移动,直至收敛到吸引子,具有相同吸引子的像素归为一类。
- 特征空间:结合颜色(如 Lab 空间)和空间位置信息,提升分割精度。
二、代码实现整体架构
代码围绕图像分割→边缘检测→性能评估→参数分析展开,核心模块如下:
1. 图像预处理与分割函数 process_image
- 功能:读取图像、缩放降采样、颜色空间转换(RGB→Lab)、Mean Shift 滤波分割、颜色量化、标签分配、Canny 边缘检测。
- 关键步骤:
- Mean Shift 滤波:
cv2.pyrMeanShiftFiltering通过空间半径(spatial_radius)和颜色半径(color_radius)聚类像素。 - 颜色量化:简化颜色种类(如除以 10 取整),减少过分割。
- 边缘检测:对聚类标签图像使用 Canny 算法提取区域边界。
- Mean Shift 滤波:
2. 性能评估函数 evaluate_segmentation
- 功能:对比分割结果与真实标签(Ground Truth),计算准确率(Precision)和召回率(Recall)。
- 核心逻辑:
- 读取并缩放真实标签图像,转换为二值图。
- 计算真阳性(TP)、假阳性(FP)、假阴性(FN),推导评估指标。
3. 参数可视化与分析
- 不同空间半径可视化:遍历多个空间半径,在原图叠加红色边缘,直观展示参数对分割结果的影响。
- 通用参数结果展示:使用固定参数(如
spatial_radius=20,color_radius=20)处理多幅图像,统一显示分割效果。 - 性能统计表格:通过 Pandas 生成 Markdown 表格,汇总多幅图像的准确率和召回率。
- 参数敏感性分析:针对单幅图像,绘制准确率 / 召回率随空间半径变化的曲线,量化参数影响。
三、代码流程总结
- 输入与预处理:
- 读取图像,缩放至 60% 尺寸(减少计算量),转换为 Lab 颜色空间(更适合颜色聚类)。
- 核心分割:
- 利用 Mean Shift 滤波聚类像素,生成初步分割结果;量化颜色以简化区域。
- 后处理:
- 分配聚类标签,通过 Canny 检测区域边缘,得到二值边缘图。
- 评估与可视化:
- 对比真实标签计算性能指标,可视化不同参数下的分割结果,分析参数影响。
四、关键参数与影响
- 空间半径(
spatial_radius):- 越大:考虑更广的空间邻域,分割区域更平滑,可能导致欠分割。
- 越小:关注局部细节,可能导致过分割。
- 颜色半径(
color_radius):- 越大:允许颜色差异更大,适合颜色相近的区域合并。
- 越小:严格区分颜色差异,适合颜色对比明显的场景。
---------------------------------------------------------------------------------------------------------------------------------
- 预处理:读取图像 → 转换为 RGB → 缩放降采样 → 转换为 Lab 颜色空间(更适合颜色分割)。
- 分割核心:使用金字塔均值漂移滤波(
pyrMeanShiftFiltering)对 Lab 图像进行聚类,得到初步分割结果。 - 后处理:颜色量化(简化颜色)→ 标签分配(每个区域一个索引)→ Canny 边缘检测(提取区域边界)。
- 输出:返回缩放后的原图(用于可视化)、边缘掩码(分割结果)和图像尺寸(用于评估)。
def process_image(image_path, spatial_radius, color_radius):
image = cv2.imread(image_path)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
height, width = image_rgb.shape[:2]
new_size = (int(width * 0.6), int(height * 0.6))
compressed = cv2.resize(image_rgb, new_size)
lab = rgb2lab(compressed)
L = (lab[:, :, 0] * 255 / 100).astype(np.uint8)
a = (lab[:, :, 1] + 128).astype(np.uint8)
b = (lab[:, :, 2] + 128).astype(np.uint8)
lab_8u = cv2.merge([L, a, b])
filtered = cv2.pyrMeanShiftFiltering(lab_8u, spatial_radius, color_radius, maxLevel=1)
quantized = (filtered

最低0.47元/天 解锁文章
5839

被折叠的 条评论
为什么被折叠?



