OpenCV系列之Meanshift和Camshift | 四十七
学习目标
在本章中,
我们将学习用于跟踪视频中对象的Meanshift和Camshift算法。
Meanshift
Meanshift背后的直觉很简单,假设你有点的集合。(它可以是像素分布,例如直方图反投影)。你会得到一个小窗口(可能是一个圆形),并且必须将该窗口移到最大像素密度(或最大点数)的区域。如下图所示:
初始窗口以蓝色圆圈显示,名称为“C1”。其原始中心以蓝色矩形标记,名称为“C1_o”。但是,如果找到该窗口内点的质心,则会得到点“C1_r”(标记为蓝色小圆圈),它是窗口的真实质心。当然,它们不匹配。因此,移动窗口,使新窗口的圆与上一个质心匹配。再次找到新的质心。很可能不会匹配。因此,再次移动它,并继续迭代,以使窗口的中心及其质心落在同一位置(或在很小的期望误差内)。因此,最终您获得的是一个具有最大像素分布的窗口。它带有一个绿色圆圈,名为“C2”。正如您在图像中看到的,它具有最大的点数。整个过程在下面的静态图像上演示:
因此,我们通常会传递直方图反投影图像和初始目标位置。当对象移动时,显然该移动会反映在直方图反投影图像中。结果,meanshift算法将窗口移动到最大密度的新位置。
OpenCV中的Meanshift
要在OpenCV中使用meanshift,首先我们需要设置目标,找到其直方图,以便我们可以将目标反投影到每帧上以计算均值偏移。我们还需要提供窗口的初始位置。对于直方图,此处仅考虑色相。另外,为避免由于光线不足而产生错误的值,可以使用cv.inRange()函数丢弃光线不足的值。
import numpy as np
import cv2 as cv
import argparse
parser = argparse.ArgumentParser(description='This sample demonstrates the meanshift algorithm. \The example file can be downloaded from: \https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
parser.add_argument('image', type=str, help='path to image file')
args = parser.parse_args()
cap = cv.VideoCapture(args.image)
# 视频的第一帧
ret,frame = cap.read()
# 设置窗口的初始位置
x, y, w, h = 300, 200, 100, 50 # simply hardcoded the values
track_window = (x, y, w, h)
# 设置初始ROI来追踪
roi = frame[y:y+h, x:x+w]
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# 设置终止条件,可以是10次迭代,也可以至少移动1 pt
term_crit = ( 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],roi_hist,[0,180],1)# 应用meanshift来获取新位置ret, track_window = cv.meanShift(dst, track_window, term_crit)# 在图像上绘制x,y,w,h = track_windowimg2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)cv.imshow('img2',img2)k = cv.waitKey(30) & 0xffif k == 27:breakelse:break
我使用的视频中的三帧如下:
Camshift
您是否密切关注了最后结果?这儿存在一个问题。无论汽车离相机很近或非常近,我们的窗口始终具有相同的大小。这是不好的。我们需要根据目标的大小和旋转来调整窗口大小。该解决方案再次来自“ OpenCV Labs”,它被称为Gary布拉德斯基(Gary Bradsky)在其1998年的论文“用于感知用户界面中的计算机视觉面部跟踪”中发表的CAMshift(连续自适应均值偏移)[26]。
它首先应用Meanshift。一旦Meanshift收敛,它将更新窗口的大小为s = 2 \times \sqrt{\frac{M_{00}}{256}}
。它还可以计算出最合适的椭圆的方向。再次将均值偏移应用于新的缩放搜索窗口和先前的窗口位置。该过程一直持续到达到要求的精度为止。
camshift_face
OpenCV中的Camshift
它与meanshift相似,但是返回一个旋转的矩形(即我们的结果)和box参数(用于在下一次迭代中作为搜索窗口传递)。请参见下面的代码:
import numpy as np
import cv2 as cv
import argparse
parser = argparse.ArgumentParser(description='This sample demonstrates the camshift algorithm. \The example file can be downloaded from: \https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
parser.add_argument('image', type=str, help='path to image file')
args = parser.parse_args()
cap = cv.VideoCapture(args.image)
# 获取视频第一帧
ret,frame = cap.read()
# 设置初始窗口
x, y, w, h = 300, 200, 100, 50 # simply hardcoded the values
track_window = (x, y, w, h)
# 设置追踪的ROI窗口
roi = frame[y:y+h, x:x+w]
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
# 设置终止条件,可以是10次迭代,有可以至少移动1个像素
term_crit = ( 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],roi_hist,[0,180],1)# 应用camshift 到新位置ret, track_window = cv.CamShift(dst, track_window, term_crit)# 在图像上画出来pts = cv.boxPoints(ret)pts = np.int0(pts)img2 = cv.polylines(frame,[pts],True, 255,2)cv.imshow('img2',img2)k = cv.waitKey(30) & 0xffif k == 27:breakelse:break
三帧的结果如下
附加资源
1.French Wikipedia page on Camshift:http://fr.wikipedia.org/wiki/Camshift. (The two animations are taken from there)
2.Bradski, G.R., "Real time face and object tracking as a component of a perceptual user interface," Applications of Computer Vision, 1998. WACV '98. Proceedings., Fourth IEEE Workshop on , vol., no., pp.214,219, 19-21 Oct 1998
Exercises
1.OpenCV comes with a Python :https://github.com/opencv/opencv/blob/master/samples/python/camshift.py for an interactive demo of camshift. Use it, hack it, understand it.
☆☆☆为方便大家查阅,小编已将OpenCV-Python专栏文章统一整理到公众号底部菜单栏,同步更新中,关注公众号,点击左下方“文章”,如图:或点击下方“阅读原文”,进入OpenCV-Python专栏,即可查看系列文章。
不断更新资源
获取更多精彩
长按二维码扫码关注
OpenCV系列之Meanshift和Camshift | 四十七相关推荐
- OpenCV均值移位(Meanshift)和Camshift算法
OpenCV Meanshift和Camshift算法 Meanshift和Camshift算法 目标 均值漂移Meanshift OpenCV中的Meanshift Camshift OpenCV中 ...
- OpenCV系列之哈里斯角检测 | 三十七
目标 在本章中, 我们将了解"Harris Corner Detection"背后的概念. 我们将看到以下函数:cv.cornerHarris(),cv.cornerSubPix( ...
- OpenCV系列之理解K-Means聚类 | 五十七
目标 在本章中,我们将了解K-Means聚类的概念,其工作原理等. 理论 我们将用一个常用的例子来处理这个问题. T-shirt尺寸问题 考虑一家公司,该公司将向市场发布新型号的T恤.显然,他们将不得 ...
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十七)远距离单体攻击与单体魔法...
到目前为止,主角能使用的魔法均为群攻型魔法,群攻魔法的原理相对简单,常见如圆形范围,矩形范围,扇形范围等等,当魔法释放后可以按照本教程的做法对所有坐标处于相应范围内的怪物进行伤害处理,这是直观的处理方 ...
- opencv中直方图和颜色跟踪相关:calcHist, calcBackProject, Meanshift和Camshift
1. 理解calcHist的应用 1)单通道hist calcHist比较好理解,就是计算 图像的直方图,单通道来说就是 灰度的分布 比如下图是灰度像素的分布,在0-255的灰度图上划分为若干个bin ...
- 使用Python,OpenCV的Meanshift 和 Camshift 算法来查找和跟踪视频中的对象
使用Python,OpenCV的Meanshift 和 Camshift 算法来查找和跟踪视频中的对象 1. 效果图 2. 源码 2.1 MeanShift 2.2 Camshift(Continuo ...
- OpenCV学习笔记(四十六)——FAST特征点检测features2D OpenCV学习笔记(四十七)——VideoWriter生成视频流highgui OpenCV学习笔记(四十八)——PCA算
OpenCV学习笔记(四十六)--FAST特征点检测features2D 特征点检测和匹配是计算机视觉中一个很有用的技术.在物体检测,视觉跟踪,三维常年关键等领域都有很广泛的应用.这一次先介绍特征点检 ...
- opencv python 多帧降噪算法_OpenCV-Python中用于视频跟踪的Meanshift和Camshift算法介绍...
学习目标 在本章中, 我们将学习用于跟踪视频中对象的Meanshift和Camshift算法. Meanshift Meanshift背后的直觉很简单,假设你有点的集合.(它可以是像素分布,例如直方图 ...
- 目标跟踪学习笔记_1(opencv中meanshift和camshift例子的应用)
在这一节中,主要讲目标跟踪的一个重要的算法Camshift,因为它是连续自使用的meanShift,所以这2个函数opencv中都有,且都很重要.为了让大家先达到一个感性认识.这节主要是看懂和运行op ...
最新文章
- 宏使用 Tricks
- 二三代基因组混合组装流程的搭建与序列拼接并行优化方法研究_武海波
- 前端面试常考知识点---js
- 每日一皮:爸爸你听我解释...
- 在python中配置MySQL数据库
- 在python子程序中、使用关键字_Python 的控制和函数
- 6 Springboot 整合Redis
- ABP理论学习之仓储
- Vue——请求转发配置解决方案
- 关于写文章的一点经验
- HDU5129 - Yong Zheng's Death
- neo4j 添加属性_Neo4j:动态添加属性/设置动态属性
- html字体代码_第50天 HTML和css的学习
- 同一个页面多个ajax提交,速度缓慢
- python 调用 .netcore api_浅谈Python调用XBee的API来进行通讯
- 无法启动mysql server问题:“1067”进程意外终止
- 延迟渲染,及材质ID
- DDOS学习+网络钓鱼+验证码攻击
- metasploit(十)漏洞攻击exploit代码编写
- java 软键盘_【学习笔记】【java appium】软键盘搜索、回车按钮