Opencv基于CamShift算法实现目标跟踪

CamShift算法全称是“Continuously Adaptive Mean-Shift”(连续的自适应MeanShift算法),是对MeanShift算法的改进算法,可以在跟踪的过程中随着目标大小的变化实时调整搜索窗口大小,对于视频序列中的每一帧还是采用MeanShift来寻找最优迭代结果,至于如何实现自动调整窗口大小的,可以查到的论述较少,我的理解是通过对MeanShift算法中零阶矩的判断实现的。
在MeanShift算法中寻找搜索窗口的质心用到窗口的零阶矩M00和一阶矩M10,M01:

零阶矩是搜索窗口内所有像素的积分,即所有像素值之和,物理上的意义是计算搜索窗口的尺寸。经过目标的H分量直方图反向投影后,目标区域的搜索窗口大部分像素值归一化后应该是最大值255,如果计算出来零阶矩大于某一阈值,可以认为此时目标铺满了整个搜索窗口,有理由认为在搜索窗口之外的区域还存在目标区域,需要增大搜索窗口的尺寸;相应的,如果零阶矩小于某一阈值,则需要缩小搜索窗口的尺寸,如此一来,当目标的大小发生变化的时候,CamShift算法就可以自适应的调整目标区域进行跟踪。

以上过程中涉及到一个关键的概念——反向投影,CamShift和MeanShift的运算都是在反向投影图像上进行的,反向投影的实现过程如下:计算并生成目标区域的H分量的直方图,反向投影其实就是把目标图像上每一个像素点的像素值替换为当前像素值所在bin对应的直方图bin的数值。

Opencv中CamShfit在使用上跟MeanShift一致:

CamShift( InputArray probImage, CV_OUT CV_IN_OUT Rect& window,
         TermCriteria criteria ); 

第一个参数probImage是反向投影图像
第二个参数window是输入和输出的搜索窗口/目标窗口,window的尺寸会自动调整
第三个参数criteria是迭代收敛终止条件

#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include "video/tracking.hpp"
#include<iostream>  

using namespace cv;
using namespace std;  

Mat image;
Mat rectImage;
Mat imageCopy; //绘制矩形框时用来拷贝原图的图像
bool leftButtonDownFlag=false; //左键单击后视频暂停播放的标志位
Point originalPoint; //矩形框起点
Point processPoint; //矩形框终点  

Mat targetImageHSV;
int histSize=200;
float histR[]={0,255};
const float *histRange=histR;
int channels[]={0,1};
Mat dstHist;
Rect rect;
vector<Point> pt; //保存目标轨迹
void onMouse(int event,int x,int y,int flags ,void* ustc); //鼠标回调函数  

int main(int argc,char*argv[])
{
 VideoCapture video(argv[1]);
 double fps=video.get(CV_CAP_PROP_FPS); //获取视频帧率
 double pauseTime=1000/fps; //两幅画面中间间隔
 namedWindow("跟踪木头人",0);
 setMouseCallback("跟踪木头人",onMouse);
 while(true)
 {
  if(!leftButtonDownFlag) //判定鼠标左键没有按下,采取播放视频,否则暂停
  {
   video>>image;
  }
  if(!image.data||waitKey(pauseTime)==27) //图像为空或Esc键按下退出播放
  {
   break;
  }
  if(originalPoint!=processPoint&&!leftButtonDownFlag)
  {
   Mat imageHSV;
   Mat calcBackImage;
   cvtColor(image,imageHSV,CV_RGB2HSV);
   calcBackProject(&imageHSV,2,channels,dstHist,calcBackImage,&histRange); //反向投影
   TermCriteria criteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, 0.001);
   CamShift(calcBackImage, rect, criteria);
   Mat imageROI=imageHSV(rect); //更新模板
   targetImageHSV=imageHSV(rect);
   calcHist(&imageROI, 2, channels, Mat(), dstHist, 1, &histSize, &histRange);
   normalize(dstHist, dstHist, 0.0, 1.0, NORM_MINMAX); //归一化
   rectangle(image, rect, Scalar(255, 0, 0),3); //目标绘制
   pt.push_back(Point(rect.x+rect.width/2,rect.y+rect.height/2));
   for(int i=0;i<pt.size()-1;i++)
   {
    line(image,pt[i],pt[i+1],Scalar(0,255,0),2.5);
   }
  }
  imshow("跟踪木头人",image);
  waitKey(100);
 }
 return 0;
}  

//*******************************************************************//
//鼠标回调函数
void onMouse(int event,int x,int y,int flags,void *ustc)
{
 if(event==CV_EVENT_LBUTTONDOWN)
 {
  leftButtonDownFlag=true; //标志位
  originalPoint=Point(x,y); //设置左键按下点的矩形起点
  processPoint=originalPoint;
 }
 if(event==CV_EVENT_MOUSEMOVE&&leftButtonDownFlag)
 {
  imageCopy=image.clone();
  processPoint=Point(x,y);
  if(originalPoint!=processPoint)
  {
   //在复制的图像上绘制矩形
   rectangle(imageCopy,originalPoint,processPoint,Scalar(255,0,0),2);
  }
  imshow("跟踪木头人",imageCopy);
 }
 if(event==CV_EVENT_LBUTTONUP)
 {
  leftButtonDownFlag=false;
  rect=Rect(originalPoint,processPoint);
  rectImage=image(rect); //子图像显示
  imshow("Sub Image",rectImage);
  cvtColor(rectImage,targetImageHSV,CV_RGB2HSV);
  imshow("targetImageHSV",targetImageHSV);
  calcHist(&targetImageHSV,2,channels,Mat(),dstHist,1,&histSize,&histRange,true,false);
  normalize(dstHist,dstHist,0,255,CV_MINMAX);
  imshow("dstHist",dstHist);
 }
}  

蓝色窗口是跟踪的目标,绿色线条是目标走过的轨迹。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • 使用OpenCV实现检测和追踪车辆
  • opencv+arduino实现物体点追踪效果
  • Opencv光流运动物体追踪详解
时间: 2018-01-06

使用OpenCV实现检测和追踪车辆

本文实例为大家分享了OpenCV实现检测和追踪车辆的具体代码,供大家参考,具体内容如下 完整源码GitHub 使用高斯混合模型(BackgroundSubtractorMOG2)对背景建模,提取出前景 使用中值滤波去掉椒盐噪声,再闭运算和开运算填充空洞 使用cvBlob库追踪车辆,我稍微修改了cvBlob源码来通过编译 由于要对背景建模,这个方法要求背景是静止的 另外不同车辆白色区域不能连通,否则会认为是同一物体 void processVideo(char* videoFilename) {

Opencv光流运动物体追踪详解

光流的概念是由一个叫Gibson的哥们在1950年提出来的.它描述是空间运动物体在观察成像平面上的像素运动的瞬时速度,利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法.那么所说的光流到底是什么? 简单来说,上图表现的就是光流,光流描述的是图像上每个像素点的灰度的位置(速度)变化情况,光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的"运动".研究光流场的目的就是为了从

opencv+arduino实现物体点追踪效果

本文所要实现的结果是:通过在摄像头中选择一个追踪点,通过pc控制摄像头的舵机,使这一点始终在图像的中心. 要点:使用光流法在舵机旋转的同时进行追踪,若该点运动,则摄像头跟踪联动. #include<opencv2\opencv.hpp> #include<opencv\cv.h> #include<opencv\highgui.h> #include<math.h> #include<Windows.h> #include<string.h

python+opencv实现动态物体追踪

简单几行就可以实现对动态物体的追踪,足见opencv在图像处理上的强大. python代码: import cv2 import numpy as np camera=cv2.VideoCapture(0) firstframe=None while True: ret,frame = camera.read() if not ret: break gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) gray=cv2.GaussianBlur(gray,(21

python opencv 检测移动物体并截图保存实例

最近在老家找工作,无奈老家工作真心太少,也没什么面试机会,不过之前面试一家公司,提了一个有意思的需求,检测河面没有有什么船只之类的物体,我当时第一反应是用opencv做识别,不过回家想想,河面相对的东西比较少,画面比较单一,只需要检测有没有移动的物体不就简单很多嘛,如果做街道垃圾检测的话可能就很复杂了,毕竟街道上行人,车辆,动物,很多干扰物,于是就花了一个小时写了一个小的demo,只需在程序同级目录创建一个img目录就可以了 # -*-coding:utf-8 -*- __author__ =

基于OpenCv的运动物体检测算法

基于一个实现的基于OpenCv的运动物体检测算法,可以用于检测行人或者其他运动物体. #include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> int main( int argc, char** argv ) //声明IplImage指针 IplImage* pFrame = NULL; IplImage* pFrImg = NULL; IplImage* pBk

WebGL three.js学习笔记之阴影与实现物体的动画效果

实现物体的旋转.跳动以及场景阴影的开启与优化 本程序将创建一个场景,并实现物体的动画效果 运行的结果如图: 运行结果 完整代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Three.js</title> <script src="../../../Import/three.js

Unity实现物体左右移动效果

本文实例为大家分享了Unity实现物体左右移动效果的具体代码,供大家参考,具体内容如下 效果如下 代码: using UnityEngine; using System.Collections; //Add this script to the platform you want to move. //左右移动的平台 public class MovingPlatform : MonoBehaviour { //Platform movement speed.平台移动速度 public floa

Python+OpenCV实现实时眼动追踪的示例代码

使用Python+OpenCV实现实时眼动追踪,不需要高端硬件简单摄像头即可实现,效果图如下所示. 项目演示参见:https://www.bilibili.com/video/av75181965/ 项目主程序如下: import sys import cv2 import numpy as np import process from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import QApplication, QMainWindow

python+opencv实现动态物体识别

注意:这种方法十分受光线变化影响 自己在家拿着手机瞎晃的成果图: 源代码: # -*- coding: utf-8 -*- """ Created on Wed Sep 27 15:47:54 2017 @author: tina """ import cv2 import numpy as np camera = cv2.VideoCapture(0) # 参数0表示第一个摄像头 # 判断视频是否打开 if (camera.isOpened()

OpenCV利用背景建模检测运动物体

本文实例为大家分享了OpenCV利用背景建模检测运动物体的具体代码,供大家参考,具体内容如下 #include <opencv\highgui.h> #include <stdio.h> int main( int argc, char** argv ){ IplImage* pFrame = NULL; IplImage* pFrImg = NULL; IplImage* pBkImg = NULL; CvMat* pFrameMat = NULL; CvMat* pFrMat