- OpenCV Python 教程
- OpenCV Python - 首页
- OpenCV Python - 概述
- OpenCV Python - 环境配置
- OpenCV Python - 读取图像
- OpenCV Python - 写入图像
- OpenCV Python - 使用Matplotlib
- OpenCV Python - 图像属性
- OpenCV Python - 位运算
- OpenCV Python - 形状和文本
- OpenCV Python - 鼠标事件
- OpenCV Python - 添加轨迹条
- OpenCV Python - 缩放和旋转
- OpenCV Python - 图像阈值化
- OpenCV Python - 图像滤波
- OpenCV Python - 边缘检测
- OpenCV Python - 直方图
- OpenCV Python - 颜色空间
- OpenCV Python - 图像变换
- OpenCV Python - 图像轮廓
- OpenCV Python - 模板匹配
- OpenCV Python - 图像金字塔
- OpenCV Python - 图像加法
- OpenCV Python - 图像融合
- OpenCV Python - 傅里叶变换
- OpenCV Python - 捕获视频
- OpenCV Python - 播放视频
- OpenCV Python - 从视频中提取图像
- OpenCV Python - 从图像生成视频
- OpenCV Python - 人脸检测
- OpenCV Python - 均值漂移/CamShift
- OpenCV Python - 特征检测
- OpenCV Python - 特征匹配
- OpenCV Python - 数字识别
- OpenCV Python 资源
- OpenCV Python - 快速指南
- OpenCV Python - 资源
- OpenCV Python - 讨论
OpenCV Python - 均值漂移和CamShift
本章我们将学习OpenCV-Python中的均值漂移和CamShift算法。首先,让我们了解什么是均值漂移。
均值漂移
均值漂移算法识别数据集中数据点高度集中的位置,或称为聚类。该算法将一个核放置在每个数据点上,并将它们加起来以生成一个**核密度估计**(KDE)。
KDE将分别具有高数据点密度和低数据点密度的位置。均值漂移是一种非常有用的方法,可以跟踪视频中特定对象。
视频的每个实例都以该帧中像素分布的形式进行检查。初始窗口作为感兴趣区域**(ROI)**,通常是正方形或圆形。为此,位置是通过硬编码指定的,并识别最大像素分布的区域。
随着视频的运行,ROI窗口向最大像素分布区域移动。移动方向取决于跟踪窗口的中心与其窗口内所有k个像素的质心之间的差异。
为了在OpenCV中使用均值漂移,首先找到目标的直方图(其中只考虑色调),然后可以将其目标反向投影到每一帧中以计算均值漂移。我们还需要提供ROI窗口的初始位置。
我们重复计算直方图的反向投影并计算均值漂移以获得跟踪窗口的新位置。之后,我们使用其尺寸在帧上绘制一个矩形。
函数
程序中使用的OpenCV函数如下:
**cv.calcBackProject()** - 计算直方图的反向投影。
**cv.meanShift()** - 使用初始搜索窗口和迭代搜索算法的停止条件来反向投影目标直方图。
示例
以下是均值漂移的示例程序:
import numpy as np import cv2 as cv cap = cv.VideoCapture('traffic.mp4') ret,frame = cap.read() # dimensions of initial location of window x, y, w, h = 300, 200, 100, 50 tracker = (x, y, w, h) region = frame[y:y+h, x:x+w] hsv_reg = cv.cvtColor(region, cv.COLOR_BGR2HSV) mask = cv.inRange(hsv_reg, np.array((0., 60.,32.)), np.array((180.,255.,255.))) reg_hist = cv.calcHist([hsv_reg],[0],mask,[180],[0,180]) cv.normalize(reg_hist,reg_hist,0,255,cv.NORM_MINMAX) # Setup the termination criteria criteria = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 ) while(1): ret, frame = cap.read() if ret == True: hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) dst = cv.calcBackProject([hsv],[0],reg_hist,[0,180],1) # apply meanshift ret, tracker = cv.meanShift(dst, tracker, criteria) # Draw it on image x,y,w,h = tracker img = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2) cv.imshow('img',img) k = cv.waitKey(30) & 0xff if k==115: cv.imwrite('capture.png', img) if k == 27: break
程序运行时,均值漂移算法将我们的窗口移动到密度最大的新位置。
输出
以下是移动窗口的快照:
CamShift
均值漂移算法的一个缺点是,跟踪窗口的大小保持不变,无论物体与摄像机的距离如何。此外,只有当物体在该物体的区域内时,窗口才会跟踪该物体。因此,我们必须手动硬编码窗口,并且必须小心地进行。
CAMshift(代表**连续自适应均值漂移**)解决了这些问题。一旦均值漂移收敛,CamShift算法就会更新窗口的大小,以便跟踪窗口的大小可能会改变,甚至旋转以更好地与被跟踪物体的运动相关联。
在下面的代码中,使用camshift()函数代替meanshift()函数。
首先,它使用meanShift查找对象的中心,然后调整窗口大小并找到最佳旋转。该函数返回对象的位姿、大小和方向。使用polylines()绘图函数在帧上绘制位姿。
示例
在之前的程序中,将Meanshift()函数替换为CamShift()函数,如下所示:
# apply camshift ret, tracker = cv.CamShift(dst, tracker, criteria) pts = cv.boxPoints(ret) pts = np.int0(pts) img = cv.polylines(frame,[pts],True, 255,2) cv.imshow('img',img)
输出
以下是修改后的程序结果的一个快照,显示了跟踪窗口的旋转矩形: