OpenCV中MeanShift图像分割

34人浏览 / 0人评论 / 添加收藏

Meanshift(均值漂移)是一种基于颜色和空间位置的非参数聚类算法,常用于图像分割。OpenCV 提供了 pyrMeanShiftFiltering 函数,可以在图像上直接得到平滑的分割结果。

原理简述

Meanshift 将每个像素看成高维空间的一个点(维度 = 空间坐标 x,y + 颜色通道 R,G,B 共5维)。算法迭代地寻找每个点在特征空间中的密度中心,流程为:

在特征空间中以某像素为起点,计算半径窗口内所有点的均值位置(颜色均值 + 空间均值)。

将窗口中心平移到该均值位置。

重复直至收敛,将该像素的颜色替换为收敛点的颜色。

对每个像素都执行,收敛到同一区域的像素形成分割块。

OpenCV 函数

void cv::pyrMeanShiftFiltering(
   InputArray src,        // 输入8位3通道图像
   OutputArray dst,       // 输出平滑分割后的图像
   double sp,             // 空间窗口半径
   double sr,             // 颜色窗口半径
   int maxLevel = 1,      // 金字塔最大层数
   TermCriteria termcrit = TermCriteria(...) // 迭代终止条件
);

参数解释

sp:空间带宽,影响空间平滑程度。越大越平滑,分割块越少。

sr:颜色带宽,影响颜色相似度合并程度。越大更多颜色被合并,分割块越少。

maxLevel:使用图像金字塔的层数(>0时会先下采样再处理,加速并提升平滑效果)。

termcrit:迭代停止条件,通常用 TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 5, 1)

 

实例代码如下:

#Meanshift图像分割
import cv2
# import numpy as np
from opencv_jupyter_ui import cv2_imshow

# 读取图像
img = cv2.imread('./images/flower.png')

# 均值漂移分割
sp = 20      # 空间半径
sr = 40      # 颜色半径
segmented = cv2.pyrMeanShiftFiltering(img, sp, sr, maxLevel=2)

# 显示结果
# cv2.imshow('Original', img)
# cv2.imshow('Meanshift Segmentation', segmented)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
cv2_imshow('Original', img)
cv2_imshow('Meanshift Segmentation', segmented)

# 可选:提取分割后的区域(连通域标记)
gray = cv2.cvtColor(segmented, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
   cv2.drawContours(img, [cnt], -1, (0,255,0), 2)

# cv2.imshow('Contours', img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
cv2_imshow('Contours', img)

效果图如下:

第一张图是原图

全部评论