【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法
【youcans 的 OpenCV 例程200篇】177.图像分割之 GraphCuts 图割法
【youcans 的 OpenCV 例程200篇】178.图像分割之 GrabCut 图割法(框选前景)
【youcans 的 OpenCV 例程200篇】179.图像分割之 GrabCut 图割法(掩模图像)
更多内容,请见:
【OpenCV 例程200篇 总目录-202206更新】
均值漂移算法(Mean Shift)是一种基于模式识别的特征空间分析方法,提供了一种目标描述与定位的算法框架。
均值漂移算法的基本思想是,通过反复迭代搜索特征空间中样本最密集的区域,搜索点沿着样本点密度增加的方向“漂移”到局部密度极大值点。采用基于核密度估计的爬山算法,自适应调整步长进行迭代搜索,可以收敛到局部极值。
基于 Mean Shift 的目标跟踪技术采用核概率密度描述目标特征,对于图像分割通常采用直方图对目标建模,然后通过相似性度量搜索目标位置,实现目标的匹配与跟踪。
对于图像分割,通常将 RGB 图像映射到 LUV 颜色特征空间,结合位置信息可以构造 5维特征变量 (x,y,l,u,v)。均值漂移算法不仅可以应用于二维图像处理,也可以用于高维数据处理。可以通过选取不同的核函数,来改变区域当中偏移向量的权重。
均值漂移算法将目标特征与空间信息有效结合,避免使用复杂模型描述目标形状、外观和运动,因此对边缘遮挡、目标旋转、变形和背景运动不敏感,能够适应目标的形状、大小的连续变换,而且计算速度快、抗干扰能力强。
均值漂移算法的缺点是:
(1)缺乏必要的模板更新;
(2)跟踪过程中由于窗口宽度大小保持不变,当目标尺度变化时,跟踪就会失败;
(3)当目标速度较快时,跟踪效果不好;
(4)直方图特征在目标颜色特征描述方面略显匮乏,缺少空间信息;
对于这些缺点,在工程实际中可以进行改进:
(1)引入目标位置变化的预测机制,以减少跟踪的搜索时间,降低计算量;
(2)将传统算法中的核函数固定带宽改为动态变化的带宽;
(3)使用前一帧的目标跟踪结果作为目标跟踪模板。
OpenCV 也提供了函数 cv.meanShift 实现均值漂移算法,该函数只考虑颜色相似性,不考虑像素的位置坐标。
该函数采用目标对象的输入反投影和初始位置,通过迭代搜索算法,计算反投影图像窗口中的质心,将搜索窗口中心移向质心,直到达到迭代终止条件。
函数说明:
cv.meanShift(probImage, window, criteria[, ]) → retval, window
cv.meanshift() 函数使用时要先设定目标,需要提供目标的初始窗口位置,计算 HSV 模型中 H (色调)的直方图。为了减少低亮度的影响,可以使用 cv.inRange() 将低亮度值忽略。
参数说明:
注意事项:
# 11.33 图像分割之均值漂移算法
def meanShiftTracker(src, trackWindow):
# meanShift 算法: 在 dst 寻找目标窗口,找到后返回目标窗口位置
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV) # BGR-HSV 转换
dst = cv2.calcBackProject([hsv], [0], roiHist, [0, 180], 1) # 计算反向投影
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
_, trackWin = cv2.meanShift(dst, trackWindow, term_crit)
x, y, w, h = trackWin
imgTrack = src.copy()
imgTrack = cv2.rectangle(imgTrack, (x, y), (x + w, y + h), 255, 2)
print(x, y, w, h)
return imgTrack
# if __name__ == '__main__': # 图像分割之均值漂移算法
img = cv2.imread("../images/FigCross1.png", flags=1) # 基准参考图像
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL) # BGR-HSV 转换
# 设置初始化的窗口位置
# print("Select a ROI and then press SPACE or ENTER button!\n")
# roi = cv2.selectROI(img, showCrosshair=True, fromCenter=False)
# x0, y0, w, h = roi # 矩形裁剪区域 (ymin:ymin+h, xmin:xmin+w) 的位置参数
# rect = (x0, y0, w, h) # 边界框矩形的坐标和尺寸 # rect = (990 311 94 72)
(x0, y0, w, h) = (990, 310, 95, 72) # 直接设置矩形窗口的位置参数,也可以鼠标框选 ROI
trackWindow = (x0, y0, w, h) # 矩形 ROI
print(x0, y0, w, h)
imgROI = np.zeros_like(img) # 创建与 image 相同形状的黑色图像
imgROI[y0:y0+h, x0:x0+w] = img[y0:y0+h, x0:x0+w].copy()
frameROI = imgROI[y0:y0+h, x0:x0+w] # 设置追踪的区域
roiHSV = cv2.cvtColor(frameROI, cv2.COLOR_BGR2HSV) # BGR-HSV 转换
# 取 HSV 在 (0,60,32)~(180,255,255) 之间的部分
mask = cv2.inRange(roiHSV, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roiHist = cv2.calcHist([roiHSV], [0], mask, [180], [0, 180]) # 计算直方图
cv2.normalize(roiHist, roiHist, 0, 255, cv2.NORM_MINMAX) # 归一化
# # meanShift 算法: 在 dst 寻找目标窗口,找到后返回目标窗口位置
img1 = cv2.imread("../images/FigCross2.png", flags=1) # 读取彩色图像(BGR)
imgTrack1 = meanShiftTracker(img1, trackWindow)
img2 = cv2.imread("../images/FigCross4.png", flags=1) # 读取彩色图像(BGR)
imgTrack2 = meanShiftTracker(img2, trackWindow)
plt.figure(figsize=(10, 6))
plt.subplot(231), plt.axis('off'), plt.title("Initial image")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 显示 img(RGB)
plt.subplot(234), plt.axis('off'), plt.title("ROI image")
plt.imshow(cv2.cvtColor(imgROI, cv2.COLOR_BGR2RGB)) # 显示 img(RGB)
plt.subplot(232), plt.axis('off'), plt.title("image 1")
plt.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)) # 显示 img(RGB)
plt.subplot(235), plt.axis('off'), plt.title("image track 1")
plt.imshow(cv2.cvtColor(imgTrack1, cv2.COLOR_BGR2RGB)) # 显示 img(RGB)
plt.subplot(233), plt.axis('off'), plt.title("image 2")
plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)) # 显示 img(RGB)
plt.subplot(236), plt.axis('off'), plt.title("image track 2")
plt.imshow(cv2.cvtColor(imgTrack2, cv2.COLOR_BGR2RGB)) # 显示 img(RGB)
plt.tight_layout()
plt.show()
程序说明:
均值漂移算法进行图像分割的效果并不是很好,所以 img2 中的目标并未成功追踪,这是由于拍摄角度导致目标物体运动后的尺寸发生了变化。不过,如果应用于视频跟踪,每次使用上一帧的目标窗口作为追踪区域,而不是一直使用初始目标窗口,由于目标在相邻帧的尺寸变化很小,可以解决这个问题。
(本节完)
版权声明:
OpenCV 例程200篇 总目录-202205更新
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/124695824)
Copyright 2022 youcans, XUPT
Crated:2022-5-8
欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中
欢迎关注 『youcans 的 OpenCV学习课』 系列,持续更新中【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法
【youcans 的 OpenCV 例程200篇】177.图像分割之 GraphCuts 图割法
【youcans 的 OpenCV 例程200篇】178.图像分割之 GrabCut 图割法(框选前景)
【youcans 的 OpenCV 例程200篇】179.图像分割之 GrabCut 图割法(掩模图像)
更多内容,请见:
【OpenCV 例程200篇 总目录-202206更新】