meanshift算法通俗讲解【meanshift实例展示】
meanshift算法原理
meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。
如下图:

最开始的窗口是蓝色圆环的区域,命名为C1。蓝色圆环的圆心用一个蓝色的矩形标注,命名为C1_o。
而窗口中所有点的点集构成的质心在蓝色圆形点C1_r处,显然圆环的形心和质心并不重合。所以,移动蓝色的窗口,使得形心与之前得到的质心重合。在新移动后的圆环的区域当中再次寻找圆环当中所包围点集的质心,然后再次移动,通常情况下,形心和质心是不重合的。不断执行上面的移动过程,直到形心和质心大致重合结束。 这样,最后圆形的窗口会落到像素分布最大的地方,也就是图中的绿色圈,命名为C2。
meanshift算法除了应用在视频追踪当中,在聚类,平滑等等各种涉及到数据以及非监督学习的场合当中均有重要应用,是一个应用广泛的算法。
图像是一个矩阵信息,如何在一个视频当中使用meanshift算法来追踪一个运动的物体呢? 大致流程如下:
1.首先在图像上选定一个目标区域
2.计算选定区域的直方图分布,一般是HSV色彩空间的直方图。
3.对下一帧图像b同样计算直方图分布。
4.计算图像b当中与选定区域直方图分布最为相似的区域,使用meanshift算法将选定区域沿着最为相似的部分进行移动,直到找到最相似的区域,便完成了在图像b中的目标追踪。
5.重复3到4的过程,就完成整个视频目标追踪。
通常情况下我们使用直方图反向投影得到的图像和第一帧目标对象的起始位置,当目标对象的移动会反映到直方图反向投影图中,meanshift 算法就把我们的窗口移动到反向投影图像中灰度密度最大的区域了。如下图所示:

直方图反向投影的流程是:
假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
1.从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
2.生成临时图像的直方图;
3.用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
4.直方图对比结果c,就是结果图像(0,0)处的像素值;
5.切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
6.重复1~5步直到输入图像的右下角,就形成了直方图的反向投影。
meanshift视频追踪实现
在OpenCV中实现Meanshift的API是:
cv.meanShift(probImage, window, criteria)
参数:
·probImage: ROI区域,即目标的直方图的反向投影
·window: 初始搜索窗口,就是定义ROI的rect
·criteria: 确定窗口搜索停止的准则,主要有迭代次数达到设置的最大值,窗口中心的漂移值大于某个设定的限值等。
实现Meanshift的主要流程是:
1.读取视频文件:cv.videoCapture()
2.感兴趣区域设置:获取第一帧图像,并设置目标区域,即感兴趣区域
3.计算直方图:计算感兴趣区域的HSV直方图,并进行归一化
4.目标追踪:设置窗口搜索停止条件,直方图反向投影,进行目标追踪,并在目标位置绘制矩形框。
示例:
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()
下面是三帧图像的跟踪结果:

Camshift算法
大家认真看下上面的结果,有一个问题,就是检测的窗口的大小是固定的,而狗狗由近及远是一个逐渐变小的过程,固定的窗口是不合适的。所以我们需要根据目标的大小和角度来对窗口的大小和角度进行修正。CamShift可以帮我们解决这个问题。
CamShift算法全称是“Continuously Adaptive Mean-Shift”(连续自适应MeanShift算法),是对MeanShift算法的改进算法,可随着跟踪目标的大小变化实时调整搜索窗口的大小,具有较好的跟踪效果。
Camshift算法首先应用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)
算法总结
meanshift
原理:一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束。
API:cv.meanshift()
优缺点:简单,迭代次数少,但无法解决目标的遮挡问题并且不能适应运动目标的的形状和大小变化
camshift
原理:对meanshift算法的改进,首先应用meanshift,一旦meanshift收敛,它就会更新窗口的大小,还计算最佳拟合椭圆的方向,从而根据目标的位置和大小更新搜索窗口。
API:cv.camshift()
优缺点:可适应运动目标的大小形状的改变,具有较好的跟踪效果,但当背景色和目标颜色接近时,容易使目标的区域变大,最终有可能导致目标跟踪丢失
相关文章:
meanshift算法通俗讲解【meanshift实例展示】
meanshift算法原理 meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。 如下图: 最开始的窗口是蓝色圆环的区域,命名为C1。蓝…...
正交变换和仿射变换
正交变换和仿射变换 平面的正交变换 正交点变换(保距变换) 平面上的一个保持任意两点距离不变的点变换 平面正交变换性质 正交变换的乘积是正交变换恒等变换是正交变换正交变换将(不)共线的三点映射成(不)…...
Electron 多端通信桥 MessageChannelMain和 MessagePortMain 坑点汇集
简介 MessageChannelMain 是 DOM MessageChannel 对象的主进程等价对象。 它的特有功能是创建一对已连接的 MessagePortMain 对象。 Electron 本身为了灵活追加 on("message") 机制,就说明该 MessageChannelMain 已经被创建了,而 Web 开发中&a…...
Html5播放器按钮在移动端变小的问题解决方法
Html5播放器按钮在移动端变小的问题解决方法 用手机浏览器打开酷播云视频,有时会出现播放器按钮太小的情况,此时只需在<head>中加入下面这段代码即可解决: <meta name"viewport" content"widthdevice-width, initia…...
Rust 开发环境搭建【一】
Rust 开发环境 推荐 搭建: 安装 rust 语言 以及 工具链 推荐安装方法:rustup curl --proto ‘https’ --tlsv1.2 -sSf https://sh.rustup.rs | sh 在国内如果访问速度慢,可以使用清华大学提供的镜像服务: https://mirrors.tu…...
C# Blazor 学习笔记(3):路由管理
文章目录 前言路由管理App.razor设置登录页面设置空布局 前言 我们知道使用Blazor的官方模板,我们会自动得到一个拥有侧边栏的布局页面。但是我们发现我们所有新建的页面都有侧边栏。有时候我们需要跳出这个布局,比如我要做登录页面的时候,我…...
int[]数组转Integer[]、List、Map「结合leetcode:第414题 第三大的数、第169题 多数元素 介绍」
文章目录 1、int[ ] 转 Integer[ ]:2、两道leetcode题遇到的场景:2.1、int[ ] 转 List<Integer> :2.2、int[ ] 转 Map: 1、int[ ] 转 Integer[ ]: public static void main(String[] args) {int[] nums {1, 2, 3}; Integer[] array Arrays.stream(nums).boxed().to…...
vue子传父的一种新方法:this.$emit(‘input‘, value)可实现实时向父组件传值
今天要说的就是利用v-model和this.$emit(‘input’,value)实现子传父。 众所周知,v-model是给input绑定,方便对表单的双向绑定。 其实,v-model是个语法糖,具体案例如下所示。 <input v-model"inputValue">相当于…...
【Web】web
dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层——传输层——网络层——数据链路层——物理层 每一定的台主机都有一个唯一且固定的地址标识——IP地址 IP地址的做用:1.区分用户和计算机;2.进行通信 IP地址由32位二进制数组成,…...
css中的bfc是什么?
什么bfc? BFC(Block Formatting Context)块级 格式化 上下文。 BFC就是页面上的一个隔离的独立盒子,容器里面的子元素和外面的元素不会相互影响。 为什么要bfc? bfc是我们去主动触发的,并不是自动就存在的,它是帮助我们解决cs…...
【前端知识】React 基础巩固(四十四)——其他Hooks(useContext、useReducer、useCallback)
React 基础巩固(四十四)——其他Hooks(useContext、useReducer、useCallback) 一、useContext的使用 在类组件开发时,我们通过 类名.contextType MyContext的方式,在类中获取context,多个Context或者在函数式组件中…...
华为云hcip核心知识笔记(数据库服务规划)
华为云hcip核心知识笔记(数据库服务规划) 1.云数据接库优势 1.1云数据库优点有: 易用性强:能欧快速部署和运行 高扩展:开放式架构和云计算存储分离 低成本:按需使用,成本更加低廉 2.云数据库r…...
【有趣的】关于Map的一些小测试
Map在代码中用到得非常多,它是无序的、key-value结构的,其读取会非常快。 今天看了个小文章Map判空 、空字符串、空key值等各种判断方法,你都掌握了吗?便自己也玩一下。 一、判空 因为对象已经new出来了,所以map指向的…...
【MATLAB第63期】基于MATLAB的改进敏感性分析方法IPCC,拥挤距离与皮尔逊系数法结合实现回归与分类预测
【MATLAB第63期】基于MATLAB的改进敏感性分析方法IPCC,拥挤距离与皮尔逊系数法结合实现回归与分类预测 思路 考虑拥挤距离指标与PCC皮尔逊相关系数法相结合,对回归或分类数据进行降维,通过SVM支持向量机交叉验证得到平均指标,来…...
AI 绘画Stable Diffusion 研究(二)sd模型ControlNet1.1 介绍与安装
部署包作者:秋葉aaaki 免责声明: 本安装包及启动器免费提供 无任何盈利目的 大家好,我是风雨无阻。 众所周知,StableDiffusion 是非常强大的AI绘图工具,需要详细了解StableDiffusion的朋友,可查看我之前的这篇文章: …...
接口参数设计原则
1. 不能太动态. 不相信客户端的原则 例如传递 filterFields , 推送一个表的某些字段给上游. 2. 可以服务端提供一些封装. 这个封装可以是写死的组合, 也可以是后端配置的. 最好的是 代码里的领域类bean 1,1对应一个名称. 可以是 classReference. 运营态有很多字段是给用户看的…...
网络安全防护利器:SK5代理与IP代理的技术对比
一、IP代理与SK5代理技术简介 IP代理: IP代理是一种通过中间服务器转发网络请求的技术。用户通过向代理服务器发出请求,代理服务器转发请求至目标服务器,然后将目标服务器的响应返回给用户。主要功能包括隐藏真实IP地址、绕过地理限制和IP封锁…...
IDEA删除本地git仓库、创建本地git仓库、关联其他仓库并上传
IDEA删除本地git仓库、创建本地git仓库、关联其他仓库并上传 删除本地Git仓库 创建本地Git仓库 关联其他仓库并上传 要在IntelliJ IDEA中删除本地Git仓库并创建新的本地Git仓库,以及关联其他仓库并上传,请按照以下步骤进行操作: 删除本地G…...
JavaEE简单示例——在使用Tomcat的时候可能出现的一些报错
简单介绍: 在我们之前使用Tomcat的时候,经常会出现在启动的时候因为一些报错导致项目无法正常的启动,我们就对一些比较常见的报错来看一下可能导致的原因,以及出现报错之后如何去解决。 严重: Failed to initialize end point a…...
webrtc的线程模型
目录 线程的声明 线程创建过程 向线程中投递消息 从消息队列中取消息的具体实现 处理线程消息 webrtc线程模块的实现逻辑在 rtc_base\thread.h 文件中 比如想创建一个线程: //声明要创建的线程指针,通过智能指针管理 std::unique_ptr<rtc::Thr…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...
