用Camshift算法对指定目标进行跟踪
原理
Camshift算法是Continuously Adaptive Mean Shift algorithm的简称。
它是一个基于MeanSift的改进算法。它首次由Gary R.Bradski等人提出和应用在人脸的跟踪上,并取得了不错的效果。因为它是利用颜色的概率信息进行的跟踪。使得它的执行效率比較高。 Camshift算法的过程由以下步骤组成:
(1)确定初始目标及其区域;
(2)计算出目标的色度(Hue)分量的直方图;
(3)利用直方图计算输入图像的反向投影图(后面做进一步的解释);
(4)利用MeanShift算法在反向投影图中迭代收索,直到其收敛或达到最大迭代次数。并保存零次矩。
(5)从第(4)步中获得收索窗体的中心位置和计算出新的窗体大小。以此为參数,进入到下一幀的目标跟踪。(即跳转到第(2)步);
代码
#include "stdafx.h"
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp" #include <iostream>
#include <ctype.h> using namespace cv;
using namespace std; Mat image; bool backprojMode = false;
bool selectObject = false;
int trackObject = 0;
bool showHist = true;
Point origin;
Rect selection(0,0,50,50); static void onMouse( int event, int x, int y, int, void* )
{
switch( event )
{
case CV_EVENT_LBUTTONDOWN:
origin = Point(x,y);
selection = Rect(x,y,0,0);
selectObject = true;
break;
case CV_EVENT_LBUTTONUP:
selectObject = false;
if( selection.width > 0 && selection.height > 0 )
trackObject = -1;
break;
}
if( selectObject )
{
selection.x = MIN(x, origin.x);
selection.y = MIN(y, origin.y);
selection.width = std::abs(x - origin.x);
selection.height = std::abs(y - origin.y);
}
} int main( int argc, const char** argv )
{
cv::VideoCapture capture(0);
capture.set( CV_CAP_PROP_FRAME_WIDTH,640);
capture.set( CV_CAP_PROP_FRAME_HEIGHT,480 );
if(!capture.isOpened())
return -1;
double rate = capture.get(CV_CAP_PROP_FPS); //获取帧率
int delay = 1000 / rate; //计算帧间延迟;
Mat frame,image,hsv,mask,hue; namedWindow("test",CV_WINDOW_AUTOSIZE);
setMouseCallback("test",onMouse,0);
while (1)
{
capture>>frame;
if(trackObject == -1){ //设置完检測的对象后開始跟踪
frame.copyTo(image);
cv::cvtColor(image,hsv,CV_RGB2HSV);
cv::inRange(hsv,Scalar(0,130,50),Scalar(180,256,256),mask); //去掉低饱和度的点
vector<cv::Mat> v;
cv::split(hsv,v); //hsv的三个通道分开
hue = v[1];
cv::Mat ROI = hue(selection); //选择感兴趣的区域
cv::Mat maskROI = mask(selection); cv::MatND hist;
int histsize[1];
histsize[0]= 16; float hranges[2];
hranges[0] = 0;
hranges[1] = 180; const float *ranges[1];
ranges[0] = hranges;
cv::calcHist(&ROI,1,0,maskROI,hist,1,histsize,ranges);//感兴趣区域的直方图。从參数太多
cv::normalize(hist,hist,0,180,CV_MINMAX); //对直方图进行归一化处理; cv::Mat backpro;
cv::calcBackProject(&hue,1,0,hist,backpro,ranges); //对h通道的进行反投影放入backpro中
backpro &= mask; cv::RotatedRect trackBox = cv::CamShift(backpro,selection,
TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER,10,1));//使用均值秒一算法找出RECT;
cv::ellipse(frame,trackBox,cv::Scalar(0,0,255),2,CV_AA);
}
cv::imshow("test",frame);
if(waitKey(30) >= 0)
break;
}
capture.release();
return 0;
}
效果
总结:
用Camshift算法对指定目标进行跟踪的更多相关文章
- Opencv目标跟踪—CamShift算法
CamShift算法全称是"Continuously Adaptive Mean-Shift"(连续的自适应MeanShift算法),是对MeanShift算法的改进算法,可以在跟 ...
- 44 dlib鼠标指定目标跟踪
dlib提供了dlib.correlation_tracker()类用于跟踪目标.官方文档入口:http://dlib.net/python/index.html#dlib.correlation_t ...
- CamShift算法
拟采用的方法,CamShift算法,即"Continuously Apative Mean-Shift"算法,是一种运动跟踪算法.它主要通过视频图像中运动物体的颜色信息来达到跟踪的 ...
- CVPR 2020几篇论文内容点评:目标检测跟踪,人脸表情识别,姿态估计,实例分割等
CVPR 2020几篇论文内容点评:目标检测跟踪,人脸表情识别,姿态估计,实例分割等 CVPR 2020中选论文放榜后,最新开源项目合集也来了. 本届CPVR共接收6656篇论文,中选1470篇,&q ...
- 吴恩达机器学习笔记47-K均值算法的优化目标、随机初始化与聚类数量的选择(Optimization Objective & Random Initialization & Choosing the Number of Clusters of K-Means Algorithm)
一.K均值算法的优化目标 K-均值最小化问题,是要最小化所有的数据点与其所关联的聚类中心点之间的距离之和,因此 K-均值的代价函数(又称畸变函数 Distortion function)为: 其中
- sqlbulkcopy 使用DataTable作为数据源的数据类型问题--来自数据源的String类型的给定值不能转换为指定目标列的类型 uniqueidentifier
今天做批量插入的时候,SQLSERVER总是报错,错误提示“来自数据源的String类型的给定值不能转换为指定目标列的类型 uniqueidentifier”. 首先核对了一下定义的dataTable ...
- SqlBulkCopy批量插入数据 显示 来自数据源的 String 类型的给定值不能转换为指定目标列的类型 smalldatetime。错误
因为需要大量插入数据,linq ef无法达到速度的要求,因此把模型转换成SQL ,使用SqlBulkCopy快速插入.但是去提示 来自数据源的 String 类型的给定值不能转换为指定目标列的类型 s ...
- 2.3 LINQ查询表达式中 使用select子句 指定目标数据
本篇讲解LINQ查询的三种形式: 查询对象 自定义查询对象某个属性 查询匿名类型结果 [1.查询结果返回集合元素] 在LINQ查询中,select子句和from子句都是必备子句.LINQ查询表达式必须 ...
- Saltstack_使用指南06_远程执行-指定目标
1. 主机规划 Targeting Minions文档 https://docs.saltstack.com/en/latest/contents.html 另请参见:自动化运维神器之saltstac ...
随机推荐
- java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()解决办法
代码改变世界 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.pre ...
- iOS学习笔记29-系统服务(二)通讯录
一.通讯录 iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库的,实现通讯录操作需要使用到AddressBook.framework框架. AddressB ...
- 刷题总结——湫湫系列故事——设计风景线(hdu4514 并差集判环+树的直径)
题目: 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好. 现在已经勘探 ...
- 【前端学习笔记】2015-09-10~~~~ css层叠样式表~~格式
关于颜色的定义: 有几种方式:1.直接接英文单词 2.#16进制 3.rgb(100%:0%:0%)或者里面写像素,此处百分号不能省略. 加多个属性时,用“;”分开 前面如果是定义标签的样式时, ...
- 转 Vim操作
传送门 vim全局替换命令 语法为 :[addr]s/源字符串/目的字符串/[option]全局替换命令为::%s/源字符串/目的字符串/g [addr] 表示检索范围,省略时表示当前行.如:“1 ...
- 使用android ndk编译boost动态库
由于以往我写过不少使用boost库开发的项目,而最近准备移植一些代码到android上(上层界面以及jni层我不管,也没研究过,现在只完成代码的移植编译,具体如何调用,由其它人负责),所以先要解决的就 ...
- PHP 几个常用的正则表达式
记录几个PHP中比较常用的正则. , $max_len = 20){ if (empty($username)) { return false; } $match = '/^(?![0-9]+$)[\ ...
- yii加载自带验证码的方法
Yii的源码包里面是自带有验证码的相关类的,因此在使用验证码的时候无需再加载外部验证码类来助阵了.下面本文将介绍一下如何在项目中加载Yii自带的验证码功能. 具体分三步: (1)在需要加载验证码的co ...
- 洛谷—— P1440 求m区间内的最小值
https://www.luogu.org/problemnew/show/P1440 题目描述 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值.若前面的 ...
- PyTorch学习笔记之n-gram模型实现
import torch import torch.nn as nn from torch.autograd import Variable import torch.nn.functional as ...