OpenCV-Python 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_window
img2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
cv.imshow('img2',img2)
k = cv.waitKey(30) & 0xff
if k == 27:
break
else:
break
我使用的视频中的三帧如下:
Camshift
您是否密切关注了最后结果?这儿存在一个问题。无论汽车离相机很近或非常近,我们的窗口始终具有相同的大小。这是不好的。我们需要根据目标的大小和旋转来调整窗口大小。该解决方案再次来自“ OpenCV Labs”,它被称为Gary布拉德斯基(Gary Bradsky)在其1998年的论文“用于感知用户界面中的计算机视觉面部跟踪”中发表的CAMshift(连续自适应均值偏移)[26]。
它首先应用Meanshift。一旦Meanshift收敛,它将更新窗口的大小为s = 2 \times \sqrt{\frac{M_{00}}{256}}。它还可以计算出最合适的椭圆的方向。再次将均值偏移应用于新的缩放搜索窗口和先前的窗口位置。该过程一直持续到达到要求的精度为止。
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) & 0xff
if k == 27:
break
else:
break
三帧的结果如下
附加资源
- French Wikipedia page on Camshift:http://fr.wikipedia.org/wiki/Camshift. (The two animations are taken from there)
- 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
- 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.
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/
欢迎关注PyTorch官方中文教程站:
http://pytorch.panchuang.net/
OpenCV中文官方文档:
http://woshicver.com/
OpenCV-Python Meanshift和Camshift | 四十七的更多相关文章
- Python之路(第四十七篇) 协程:greenlet模块\gevent模块\asyncio模块
一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程,最大的区别在于 ...
- Python学习笔记(四十七)SMTP发送邮件
摘抄自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432005226 ...
- 孤荷凌寒自学python第四十七天通用跨数据库同一数据库中复制数据表函数
孤荷凌寒自学python第四十七天通用跨数据库同一数据库中复制数据表函数 (完整学习过程屏幕记录视频地址在文末) 今天继续建构自感觉用起来顺手些的自定义模块和类的代码. 今天打算完成的是通用的(至少目 ...
- opencv笔记--meanshift&camshift
meanshift 被应用于 object track 中,其主要思想如下: 如下图所示,对该点集应用 meanshift 算法可以定位到点集最稠密位置,而点集最稠密位置即为我们需要跟踪的物体位置. ...
- 【图像处理】OpenCV+Python图像处理入门教程(四)几何变换
这篇随笔介绍使用OpenCV进行图像处理的第四章 几何变换. 4 几何变换 图像的几何变换是指将一幅图像映射到另一幅图像内.有缩放.翻转.仿射变换.透视.重映射等操作. 4.1 缩放 使用cv2. ...
- OpenCV Python教程(3、直方图的计算与显示)
转载请详细注明原作者及出处,谢谢! 本篇文章介绍如何用OpenCV Python来计算直方图,并简略介绍用NumPy和Matplotlib计算和绘制直方图 直方图的背景知识.用途什么的就直接略过去了. ...
- 目标跟踪之camshift---opencv中meanshift和camshift例子的应用
在这一节中,主要讲目标跟踪的一个重要的算法Camshift,因为它是连续自使用的meanShift,所以这2个函数opencv中都有,且都很重要.为了让大家先达到一个感性认识.这节主要是看懂和运行op ...
- 20192204 2019-2020-2 《Python程序设计》实验四报告
20192204 2019-2020-2 <Python程序设计>实验四报告 课程:<Python程序设计> 班级: 1922 姓名: 李龙威 学号:20192204 实验教师 ...
- python学习心得第四章
python 学习心得第四章 1.lambda表达式 1:什么是lambda表达式 为了简化简单函数的代码,选择使用lambda表达式 上面两个函数的表达式虽然不一样,但是本质是一样的,并且lamb ...
随机推荐
- Docker+Cmd+Cli+Git之前端工程化纪要(一)整体目标
之前一版的工程化核心产物就是一个IDE,即利用python+node将webpack等技术将FE的开发.编译.部署上线等环境集成在sublime中,产出了一个核心工具.但随着长期的使用与技术栈的优化升 ...
- 分割文件和数据(linux)
在某些情况下,必须把文件分割成多个更小的片段.如今我们分割文件的目的比如:提高可读性.生成日志.通过Email发送文件等等. 假设我们有一个erro.log的测试文件,其大小为14M.你可以将该文件分 ...
- 渗透之——MSF提权
在WEB渗透中当我们拿到webshell了,我们可以试试用MSF(metasploit)来进行提权,在MSF里meterpreter很强大的! 我们先用msfvenom生成一个EXE的木马后门. ms ...
- 完整版EXCEL导出 (大框架SpringCloud 业务还是Springboot一套)
这里用的是easypoi 首先引入jar包 <!-- excel --><dependency> <groupId>cn.afterturn</groupId ...
- MySQL占用CPU超过百分之100解决过程
本文转载自: https://www.93bok.com 访问网页504 Gateway Time-out,登陆服务器查看,内存正常,CPU使用率达到了400%,因为是4核,所以到了400%,几乎全部 ...
- preload & prefetch
原文地址在 我的笔记里,觉得还行就给个 star 吧:) 关于 preload 和 prefetch 早有耳闻,知道它们可以优化页面加载速度,然具体情况却了解不多.搜索了相关的资料后对其有了些认识,在 ...
- 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/VdOKQG 可交互视频 此视频是可 ...
- Wireshark网络分析就这么简单——读书笔记
前言 什么是wireshark? wireshark可能是世界上最好的开源网络分析器,能在多个平台上(Linux.Mac和Windows)抓取和分析网络包 wireshark分析常见的协议,可以在学习 ...
- Let’s Encrypt https证书安装
我的博客: https://www.seyana.life/post/15 现在已经有很多的免费ssl证书提供商,国内的也有, 不过国内政策要求还要把key给他们, 我们还是用Let's Encryp ...
- redis如何在spring里面的bean配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...