Lesson5-2:OpenCV视频操作---视频追踪
学习目标
- 理解
meanshift
的原理 - 知道
camshift
算法 - 能够使用
meanshift
和Camshift
进行目标追踪
1.meanshift
1.1原理
m e a n s h i f t meanshift meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。
如下图:
最开始的窗口是蓝色圆环的区域,命名为 C 1 C1 C1。蓝色圆环的圆心用一个蓝色的矩形标注,命名为C1_o。
而窗口中所有点的点集构成的质心在蓝色圆形点C1_r处,显然圆环的形心和质心并不重合。所以,移动蓝色的窗口,使得形心与之前得到的质心重合。在新移动后的圆环的区域当中再次寻找圆环当中所包围点集的质心,然后再次移动,通常情况下,形心和质心是不重合的。不断执行上面的移动过程,直到形心和质心大致重合结束。 这样,最后圆形的窗口会落到像素分布最大的地方,也就是图中的绿色圈,命名为C2。
m e a n s h i f t meanshift meanshift算法除了应用在视频追踪当中,在聚类,平滑等等各种涉及到数据以及非监督学习的场合当中均有重要应用,是一个应用广泛的算法。
图像是一个矩阵信息,如何在一个视频当中使用 m e a n s h i f t meanshift meanshift算法来追踪一个运动的物体呢? 大致流程如下:
-
首先在图像上选定一个目标区域
-
计算选定区域的直方图分布,一般是HSV色彩空间的直方图。
-
对下一帧图像b同样计算直方图分布。
-
计算图像 b b b当中与选定区域直方图分布最为相似的区域,使用 m e a n s h i f t meanshift meanshift算法将选定区域沿着最为相似的部分进行移动,直到找到最相似的区域,便完成了在图像b中的目标追踪。
-
重复3到4的过程,就完成整个视频目标追踪。
通常情况下我们使用直方图反向投影得到的图像和第一帧目标对象的起始位置,当目标对象的移动会反映到直方图反向投影图中,meanshift 算法就把我们的窗口移动到反向投影图像中灰度密度最大的区域了。如下图所示:
直方图反向投影的流程是:
假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
- 从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
- 生成临时图像的直方图;
- 用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
- 直方图对比结果c,就是结果图像(0,0)处的像素值;
- 切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
- 重复1~5步直到输入图像的右下角,就形成了直方图的反向投影。
1.2 实现
在OpenCV中实现Meanshift的API是:
cv.meanShift(probImage, window, criteria)
参数:
-
probImage
: ROI区域,即目标的直方图的反向投影 -
window
: 初始搜索窗口,就是定义ROI的rect -
criteria
: 确定窗口搜索停止的准则,主要有迭代次数达到设置的最大值,窗口中心的漂移值大于某个设定的限值等。
实现Meanshift的主要流程是:
- 读取视频文件:
cv.videoCapture()
- 感兴趣区域设置:获取第一帧图像,并设置目标区域,即感兴趣区域
- 计算直方图:计算感兴趣区域的
HSV
直方图,并进行归一化 - 目标追踪:设置窗口搜索停止条件,直方图反向投影,进行目标追踪,并在目标位置绘制矩形框。
示例:
import numpy as np
import cv2 as cv
# 1.获取图像
cap = cv.VideoCapture('DOG.wmv')# 2.获取第一帧图像,并指定目标位置
ret,frame = cap.read()
# 2.1 目标位置(行,高,列,宽)
r,h,c,w = 197,141,0,208
track_window = (c,r,w,h)
# 2.2 指定目标的感兴趣区域
roi = frame[r:r+h, c:c+w]# 3. 计算直方图
# 3.1 转换色彩空间(HSV)
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
# 3.2 去除低亮度的值
# mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
# 3.3 计算直方图
roi_hist = cv.calcHist([hsv_roi],[0],None,[180],[0,180])
# 3.4 归一化
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)# 4. 目标追踪
# 4.1 设置窗口搜索终止条件:最大迭代次数,窗口中心漂移最小值
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )while(True):# 4.2 获取每一帧图像ret ,frame = cap.read()if ret == True:# 4.3 计算直方图的反向投影hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)# 4.4 进行meanshift追踪ret, track_window = cv.meanShift(dst, track_window, term_crit)# 4.5 将追踪的位置绘制在视频上,并进行显示x,y,w,h = track_windowimg2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)cv.imshow('frame',img2)if cv.waitKey(60) & 0xFF == ord('q'):break else:break
# 5. 资源释放
cap.release()
cv.destroyAllWindows()
下面是三帧图像的跟踪结果:
2 Camshift
大家认真看下上面的结果,有一个问题,就是检测的窗口的大小是固定的,而狗狗由近及远是一个逐渐变小的过程,固定的窗口是不合适的。所以我们需要根据目标的大小和角度来对窗口的大小和角度进行修正。 C a m S h i f t CamShift CamShift可以帮我们解决这个问题。
C a m S h i f t CamShift CamShift算法全称是“Continuously Adaptive Mean-Shift”(连续自适应MeanShift算法),是对MeanShift算法的改进算法,可随着跟踪目标的大小变化实时调整搜索窗口的大小,具有较好的跟踪效果。
C a m s h i f t Camshift Camshift算法首先应用 m e a n s h i f t meanshift meanshift,一旦 m e a n s h i f t meanshift meanshift收敛,它就会更新窗口的大小,还计算最佳拟合椭圆的方向,从而根据目标的位置和大小更新搜索窗口。如下图所示:
Camshift在OpenCV中实现时,只需将上述的meanshift函数改为Camshift函数即可:
将Camshift中的:
# 4.4 进行meanshift追踪ret, track_window = cv.meanShift(dst, track_window, term_crit)# 4.5 将追踪的位置绘制在视频上,并进行显示x,y,w,h = track_windowimg2 = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
改为:
#进行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)
3 算法总结
Meanshift和camshift算法都各有优势,自然也有劣势:
-
Meanshift算法:简单,迭代次数少,但无法解决目标的遮挡问题并且不能适应运动目标的的形状和大小变化。
-
camshift算法:可适应运动目标的大小形状的改变,具有较好的跟踪效果,但当背景色和目标颜色接近时,容易使目标的区域变大,最终有可能导致目标跟踪丢失。
总结
-
meanshift
原理:一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束。
API:
cv.meanshift()
优缺点:简单,迭代次数少,但无法解决目标的遮挡问题并且不能适应运动目标的的形状和大小变化
-
camshift
原理:对meanshift算法的改进,首先应用meanshift,一旦meanshift收敛,它就会更新窗口的大小,还计算最佳拟合椭圆的方向,从而根据目标的位置和大小更新搜索窗口。
API:
cv.camshift()
优缺点:可适应运动目标的大小形状的改变,具有较好的跟踪效果,但当背景色和目标颜色接近时,容易使目标的区域变大,最终有可能导致目标跟踪丢失
相关文章:

Lesson5-2:OpenCV视频操作---视频追踪
学习目标 理解meanshift的原理知道camshift算法能够使用meanshift和Camshift进行目标追踪 1.meanshift 1.1原理 m e a n s h i f t meanshift meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可…...

1778_树莓派系统安装
全部学习汇总: GitHub - GreyZhang/little_bits_of_raspberry_pi: my hacking trip about raspberry pi. 一段视频学习教程的总结,对我来说基本上用处不大。因为我自己的树莓派简简单单安装完就开机成功了,而且实现了很多视频中介绍的功能。 …...

关闭jenkins插件提醒信息
jenkins提醒信息和安全警告可以帮助我们了解插件或者jenkins的更新情况,但是有些插件是已经不维护了,提醒却一直存在,看着糟心,就像下面的提示 1、关闭插件提醒 找到如下位置:系统管理-系统配置-管理监控配置 打开管…...

JixiPix Artista Impresso Pro for mac(油画滤镜效果软件)
JixiPix Artista Impresso pro Mac是一款专业的图像编辑软件,专为Mac用户设计。它提供了各种高质量的图像编辑工具,可以帮助您创建令人惊叹的图像。该软件具有直观的用户界面,使您可以轻松地浏览和使用各种工具。 它还支持多种文件格式&…...

机器学习之 Jupyter Notebook 使用
🎈 作者:Linux猿 🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊! &…...

Unity引擎修改模型顶点色的工具
大家好,我是阿赵。 之前分享过怎样通过MaxScript在3DsMax里面修改模型的顶点色。不过由于很多时候顶点色的编辑需要根据在游戏引擎里面的实际情况和shader的情况来动态调整,所以如果能在引擎里面直接修改模型的顶点色,将会方便很多。于是…...

linux安装minio以及springboot整合使用
文章目录 1.linux安装minio2.springboot整合minio使用 1.linux安装minio 1.新建文件夹 mkdir /home/minio # 数据文件夹 mkdir /home/minio/data # 创建日志文件夹 mkdir /home/minio/log2.进入文件夹 cd /home/minio3.下载minio,链接可从官网获取 wget https://…...

javaee 事务 事务的特性 事务的并发问题 事务的隔离级别
什么是事务(Transaction) 是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,sql 能将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性。事务…...

Matlab怎么引入外部的latex包?Matlab怎么使用特殊字符?
Matlab怎么引入外部的latex包?Matlab怎么使用特殊字符? Matlab怎么使用特殊字符?一种是使用latex方式,Matlab支持基本的Latex字符【这里】,但一些字符需要依赖外部的包,例如“𝔼”,需…...

day-07 I/O复用(select)
一.I/O复用 (一)基于I/O复用的服务器端 1.多进程服务器 每次服务都需要创建一个进程,需要大量的运算和内存空间 2.复用 只需创建一个进程。 3.复用技术在服务器端的应用 (二)select函数实现服务器端 (…...

Glide的使用及源码分析
前言 依赖 implementation com.github.bumptech.glide:glide:4.16.0 github: GitHub - bumptech/glide: An image loading and caching library for Android focused on smooth scrolling 基本使用 //加载url Glide.with(this) .load(url) .placeholder(R.drawable.placehol…...

外贸爬虫系统
全球智能搜索 全球智能搜索 支持全球所有国家搜索引擎,及社交平台,精准定位优质的外贸客户,免翻墙 全球任意国家地区实时采集 搜索引擎全网邮箱电话采集 社交平台一键查看采集(Facebook,Twitter,Linkedin等) 职位…...

CentOS 8 安装 Code Igniter 4
在安装好LNMP运行环境基础上,将codeigniter4文件夹移动到/var/nginx/html根目录下,浏览器地址栏输入IP/codeigniter/pulbic 一直提示: Cache unable to write to "/var/nginx/html/codeigniter/writable/cache/". 找了好久&…...

.net framework 提示安装了 但是删除面板看不到
如果你在计算机上安装了.NET Framework,但在“控制面板”中找不到.NET Framework的相关条目,可能是因为.NET Framework的某些组件或特定版本未在“程序和功能”(或旧版本的Windows中称为“程序和功能”)列表中列出。这可能是正常情…...

flask-smorest 库
flask-smorest 简介 flask-smorest: 基于Flask/Marshmallow的REST API框架 flask-smorest 是一个用于创建于数据库无关的REST API的架库。 它使用Flask作为Web服务器,并使用marsmallow对数据进行序列化和反序列化。(类似于drf) 快速入门 flask-smorest对代码应…...

android WindowManager的简单使用
<?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"><uses-permission android:name"android.permis…...

Spark_Spark比mapreduce快的原因
Spark 为什么比 mapreduce 快? 最重要的3点, 数据缓存 : 中间结果可以缓存在内存中复用 资源管理 :executor task 管理,不同stage的task可以运行在同一个executor上 任务调度 : dag 对比多阶段mr 1.任务模型的优化(DAG图对比…...

el-upload调用内部方法删除文件
从Element UI 的官方文档中, Upload 上传组组件提供了on-remove和before-remove的文件删除的钩子属性(回调方法名),但如何调用组件删除方法(让该方法删除本地上传文件列表以及触发这两个钩子)并无相关说明。…...

无涯教程-JavaScript - CUBEKPIMEMBER函数
描述 该函数返回关键绩效指标(KPI)属性,并在单元格中显示KPI名称。 语法 CUBEKPIMEMBER (connection, kpi_name, kpi_property, [caption])争论 Argument描述Required/OptionalconnectionName of the connection to the cube - A text stringRequiredkpi_nameName of the K…...

代码随想录Day_52打卡
①、最长递增子序列 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序…...

692. 前K个高频单词
题目来源:力扣 题目描述: 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。 示例 1: 输入:…...

介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用
Docker 是一个开源的容器化平台,可以让开发者将应用程序和其所依赖的组件(如库、运行环境)打包成一个可移植、自包含的容器。这个容器可以在任何支持 Docker 的环境中运行,包括开发、测试、生产等环境。Docker 的基本概念包括以下…...

C++:构建一个二叉树的代码
#include <iostream>// 定义二叉树节点 struct BinaryTreeNode {int data;BinaryTreeNode* left;BinaryTreeNode* right;BinaryTreeNode(int val) : data(val), left(nullptr), right(nullptr) {} };// 构建二叉树 BinaryTreeNode* buildBinaryTree() {int val;std::ci…...

iOS 设置下载部分文件,如何获取完整文件的大小
在视频的需求中,遇到这样一个需求,播放一视频的时候,要预下载 后面10条视频,但是只下载后面十条视频的前面1M 实现方法 1 创建请求时设置cacheLength resource [[IdiotResource alloc] init];resource.requestURL task.request…...

如何助力金融贷款企业实现精准营销获客
无论是哪个行业,吸引客户都是核心。 许多公司的线下渠道面临着许多障碍,以至于他们不得不采用在线客户获取方法。受影响最大的行业之一是贷款行业。如何获得准确的贷款客户资源?如何赢得客户已经成为企业的一大痛点。 过去,信贷…...

html中的换行(\n)或回车(\r)符号不起作用的解决办法、br、white、space、pre、line
文章目录 前言html不解释空白字符CSS样式的影响特定的文本区域white-space 前言 如果您的HTML中的换行和回车符号(\n和\r)似乎不起作用,可能有几种可能的原因: html不解释空白字符 在HTML中,连续的空白字符࿰…...

SpringBoot+MyBatisPlus+MySql+vue2+elementUi的案例、java访问数据库服务、java提供接口服务
文章目录 前言后端关键代码前端关键代码完整代码 前言 1、项目不使用前后端分离。 2、在创建SpringBoot的时候要注意各个插件间的版本问题。 3、后端技术SpringBootMyBatisPlusMySql。 4、前端技术vue2elementUi。 后端关键代码 简单介绍 1、数据库名称ssm_db 2、表名称tbl_bo…...

设计模式入门(二)观察者模式
设计模式入门 本系列所有内容参考自《HeadFirst设计模式》。因为书中的代码是采用java语言写的,博主这里用C语言改写。 这里采用讲故事的方式进行讲解。若有错误之处,非常欢迎大家指导。 设计模式:模式不是代码,而针对设计问题的…...

列化复杂的xml对应的类
你能帮我写一个序列化复杂的xml对应的类吗? c#代码 好的,可以试着为一个复杂的XML生成对应的C#类。这里我就简单的XML为例: <Book><Name>Design Patterns</Name><Author>Erich Gamma</Author><Pages>395</Pages><Chapters>…...

什么是软件开发生命周期(SDLC)?
软件开发生命周期(SDLC)指的是从软件项目开始到最终交付的整个过程。它是软件开发过程的指导框架,用于规划、开发、测试、部署和维护软件系统。 SDLC包含了一系列阶段,每个阶段都有特定的任务、活动和产物。这些阶段通常包括以下…...