因为采用的是camshift算法,所以其基本思想是以视频图像中运动物体的颜色信息作为特征;

运行代码如下:

//采用camshift算法
#include <opencv2/core/utility.hpp>
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"#include <iostream>
#include <ctype.h>using namespace cv;
using namespace std;Mat image;bool backprojMode = false;//表示是否要进入反向投影模式,true则表示要进入反向投影模式
bool selectObject = false;//表是否在选中要跟踪的初始目标,true表示正在用鼠标选择要跟踪的目标
int trackObject = 0;//跟踪目标的数目
bool showHist = true;//是否显示HUE分量直方图
Point origin;//用于保存鼠标选择第一次单击时点的位置
Rect selection;//用于保存鼠标选择的矩形框
int vmin = 10, vmax = 256, smin = 30;
//用于设置滑动条;
// User draws box around object to track. This triggers CAMShift to start tracking
static void onMouse( int event, int x, int y, int, void* )
//用于鼠标回调函数;该函数用鼠标进行跟踪目标的选择;
{switch( event )//鼠标事件;{case EVENT_LBUTTONDOWN://鼠标按下,开始点击选择跟踪物体;selectObject = true;//鼠标按下赋予真值;origin = Point(x,y);//保存鼠标左键点击获得的点;selection = Rect(x,y,0,0);//鼠标按下去时初始化一个矩形区域;//这里一定要初始化,宽和高为(0,0)是因为在opencv中Rect矩形框类内的点是包含左上角那个点的,但是不含右下角那个点break;case EVENT_LBUTTONUP://鼠标左键松开;selectObject = false;if( selection.width > 0 && selection.height > 0 )//如果选择的物体有效则打开跟随功能;trackObject = -1;   // Set up CAMShift properties in main() loopbreak;}if( selectObject )//如果selectObject为1,则表示目标进行目标选择;此时对矩形类selection用当前的鼠标位置进行设置;{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);selection &= Rect(0, 0, image.cols, image.rows);//保证所选的矩形框在显示区域内;}}string hot_keys ="\n\nHot keys: \n""\tESC - quit the program\n""\tc - stop the tracking\n""\tb - switch to/from backprojection view\n""\th - show/hide object histogram\n""\tp - pause video\n""To initialize tracking, select the object with mouse\n";static void help()//帮助文档;
{cout << "\nThis is a demo that shows mean-shift based tracking\n""You select a color objects such as your face and it tracks it.\n""This reads from video camera (0 by default, or the camera number the user enters\n""Usage: \n""   ./camshiftdemo [camera number]\n";cout << hot_keys;
}const char* keys ={"{help h | | show help message}{@camera_number| 0 | camera number}"};int main( int argc, const char** argv )
{VideoCapture cap;Rect trackWindow;int hsize = 16;//划分直方图bin的个数,越多越精确;float hranges[] = {0,180};//像素值的取值范围;const float* phranges = hranges;//用于初始化CvHistogram类CommandLineParser parser(argc, argv, keys);//命令解析函数if (parser.has("help")){help();return 0;}int camNum = parser.get<int>(0);cap.open(camNum);if( !cap.isOpened() )//摄像头没有打开的帮助文件;{help();cout << "***Could not initialize capturing...***\n";cout << "Current parameter's value: \n";parser.printMessage();return -1;}cout << hot_keys;namedWindow( "Histogram", 0 );//用于显示直方图;namedWindow( "CamShift Demo", 0 );setMouseCallback( "CamShift Demo", onMouse, 0 );//设置鼠标回调函数;createTrackbar( "Vmin", "CamShift Demo", &vmin, 256, 0 );createTrackbar( "Vmax", "CamShift Demo", &vmax, 256, 0 );createTrackbar( "Smin", "CamShift Demo", &smin, 256, 0 );//设置的滑动条;Mat frame, hsv, hue, mask, hist,histimg = Mat::zeros(200, 320, CV_8UC3), backproj;bool paused = false;for(;;)//用于处理的主要函数;{if( !paused )//不暂停{cap >> frame;//从摄像头抓取一帧图像放在frame中;if( frame.empty() )break;}frame.copyTo(image);//把frame中的图像复制给image;if( !paused ){cvtColor(image, hsv, COLOR_BGR2HSV);//把摄像头图像从RGB表色系转为HSV表色系if( trackObject )//traekObject初始为0;或者键盘输入c后也为0;用鼠标单击后为-1;//如果trackObject不为0,则表示有需要跟踪的物体;{int _vmin = vmin, _vmax = vmax;/*inRange函数的功能是检可以查输入数组每个元素大小是否在2个给定数值之间,* 是多通道的,mask保存0通道的最小值,也就是h分量这里利用了hsv的3个通道,* 比较h,0~180,s,smin~256,v,min(vmin,vmax),max(vmin,vmax)。如果* 3个通道都在对应的范围内,则mask对应的那个点的值全为1(0xff),否则为0(0x00).*/inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)),Scalar(180, 256, MAX(_vmin, _vmax)), mask);//制作掩膜板,只处理像素值为H:0~180,S:smin~256,V:vmin~vmax之间的部分int ch[] = {0, 0};hue.create(hsv.size(), hsv.depth());/*hue初始化为与hsv大小深度一样的矩阵,色调的度量是用角度表示的,* 红绿蓝之间相差120度,反色相差180度*/mixChannels(&hsv, 1, &hue, 1, ch, 1);//hsv的1通道复制到hue的1通道;if( trackObject < 0 )//鼠标区域松开后,该函数内部又将其赋值为1;{// Object has been selected by user, set up CAMShift search properties onceMat roi(hue, selection), maskroi(mask, selection);/*此处的构造函数roi用的是Mat hue的矩阵头,且roi的数据指针指向hue,* 即共用相同的数据,select为其感兴趣的区域*/calcHist(&roi, 1, 0,maskroi, hist,1, &hsize, &phranges);/*calcHist()函数第一个参数为输入矩阵序列,第2个参数表示输入的矩阵数目,* 第3个参数表示将被计算直方图维数通道的列表,第4个参数表示可选的掩码函* 数,第5个参数表示输出直方图,第6个参数表示直方图的维数,第7个参数为每* 一维直方图数组的大小,第8个参数为每一维直方图bin的边界*///将roi的0通道计算直方图并通过mask放入hist中,hsize为每一维直方图的大小normalize(hist, hist, 0, 255, NORM_MINMAX);//将hist矩阵进行数组范围归一化,都归一化到0-255trackWindow = selection;trackObject = 1; // Don't set up again, unless user selects new ROI/*置track_object为1,表明属性提取完成,只要鼠标选完区域松开后,*且没有按键盘清0键'c',则trackObject一直保持为1,因此该if函* 数只能执行一次,除非重新选择跟踪区域*/histimg = Scalar::all(0);//与按下‘c’键是一样的,这里的all(0)表示的是标量全部清0int binW = histimg.cols / hsize;//histing是一个200*300的矩阵,hsize应该是每一个bin的宽度,也就是histing矩阵能分出几个bin出来Mat buf(1, hsize, CV_8UC3);//定义一个缓冲单bin矩阵for( int i = 0; i < hsize; i++ )//saturate_case函数为从一个初始类型准确变换到另一个初始类型buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize), 255, 255);cvtColor(buf, buf, COLOR_HSV2BGR);//hsv又转换成bgrfor( int i = 0; i < hsize; i++ ){int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows/255);/*at函数为返回一个指定数组元素的参考值*/rectangle( histimg, Point(i*binW,histimg.rows),Point((i+1)*binW,histimg.rows - val),Scalar(buf.at<Vec3b>(i)), 3, 8 );//在一幅输入图像上画一个简单抽的矩形,指定左上角和右下角,并定义颜色,大小,线型等}}// Perform CAMShiftcalcBackProject(&hue, 1, 0, hist, backproj, &phranges);//计算hue的反向投影图,计算hue图像0通道直方图hist的反向投影,并放入backproj中backproj &= mask;RotatedRect trackBox = CamShift(backproj, trackWindow,TermCriteria( TermCriteria::EPS | TermCriteria::COUNT,10, 1 ));//trackWindow为鼠标选择的区域,TermCriteria为确定迭代终止的准则if( trackWindow.area() <= 1 ){int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,trackWindow.x + r, trackWindow.y + r) &Rect(0, 0, cols, rows);}if( backprojMode )cvtColor( backproj, image, COLOR_GRAY2BGR );
//                  ellipse( image, trackBox, Scalar(0,0,255), 3, LINE_AA );rectangle(image,Point(trackWindow.x,trackWindow.y),Point(trackWindow.x+trackWindow.width,trackWindow.y+trackWindow.height),Scalar(255,0,0),3,CV_AA);}}else if( trackObject < 0 )paused = false;if( selectObject && selection.width > 0 && selection.height > 0 )//如果正处于物体选择,画出选择框{Mat roi(image, selection);bitwise_not(roi, roi);// bitwise_not为将每一个bit位取反}imshow( "CamShift Demo", image );imshow( "Histogram", histimg );char c = (char)waitKey(10);if( c == 27 )break;switch(c){case 'b':backprojMode = !backprojMode;break;case 'c':trackObject = 0;histimg = Scalar::all(0);break;case 'h':showHist = !showHist;if( !showHist )destroyWindow( "Histogram" );elsenamedWindow( "Histogram", 1 );break;case 'p':paused = !paused;break;default:;}}return 0;
}

具体操作即用鼠标框选目标即可;

实现效果如下:

呈现效果

其中的命令解析函数的使用:

打开运行文件所在位置,带开终端,输入./文件名 -h  即可;效果如下:

Ubuntu下camshift算法进行目标跟踪相关推荐

  1. kcf算法流程_基于运动检测与KCF算法的目标跟踪方法

    基于运动检测与 KCF 算法的目标跟踪方法 易 诗,唐 文 [摘 要] 摘要:近年来机器视觉技术广泛采用于各个领域,本文设计实现了一 种基于运动检测与 KCF 算法的目标跟踪方法,该方法相对于传统单一 ...

  2. 传统目标跟踪方法简介

    前言:由于个人之前做过一个目标跟踪算法,所以,有必要将之前的工作做一个梳理. 目录 基于第一种思路的运动目标检测 1. 静态背景: 2. 运动场 目标跟踪: 相似性度量算法: 核心搜索算法: 卡尔曼滤 ...

  3. 目标跟踪算法的分类(一)

    运动目标跟踪主流算法大致分类 主要基于两种思路: a)不依赖于先验知识,直接从图像序列中检测到运动目标,并进行目标识别,最终跟踪感兴趣的运动目标: b)依赖于目标的先验知识,首先为运动目标建模,然后在 ...

  4. kcf 跟随_基于YOLO和KCF的目标跟踪算法研究

    1. 引言 随着AI技术的不断发展,其子领域计算机视觉技术也获得了突飞猛进的进步,计算机视觉即通过机器实现"人眼"对事物的测量和判别能力.目前,计算机视觉技术主要应用于智能视频监控 ...

  5. Video Target Tracking Based on Online Learning—TLD单目标跟踪算法详解

    视频目标跟踪问题分析         视频跟踪技术的主要目的是从复杂多变的的背景环境中准确提取相关的目标特征,准确地识别出跟踪目标,并且对目标的位置和姿态等信息精确地定位,为后续目标物体行为分析提供足 ...

  6. 交互式多模型算法IMM——机动目标跟踪中的应用

    机动目标跟踪--交互式多模型算法IMM 原创不易,路过的各位大佬请点个赞 WX: ZB823618313 机动目标跟踪--交互式多模型算法IMM 机动目标跟踪--交互式多模型算法IMM 1. 对机动目 ...

  7. STAPLE目标跟踪算法(C++ /OpenCV)

    简介 结合梯度特征HOG及颜色特征的实时跟踪算法,速度可以达到80FPS. 摘要 近些年来,基于相关滤波跟踪器的算法得到了很大的改进,已经能够达到很好的跟踪效果,14年的KCF,15年的SRDCF.H ...

  8. 深度学习自学(二十五):目标跟踪

    运动目标跟踪主流算法大致分类 主要基于两种思路: a)不依赖于先验知识,直接从图像序列中检测到运动目标,并进行目标识别,最终跟踪感兴趣的运动目标:  b)依赖于目标的先验知识,首先为运动目标建模,然后 ...

  9. opencv动态目标跟踪学习总结

    用opencv实现对视频中动态目标的追踪 第一步,是要建立一个编程环境,然后加载opencv的库路径等等.具体步骤在 http://www.opencv.org.cn/ 的"安装" ...

  10. python-opencv打开Azure-Kincet DK相机显示RGB,深度图和点云图,并使用KCF实现单目标跟踪

    本项目使用python-opencv打开Azure-Kincet DK相机,并显示RGB,深度图和点云图和KCF目标跟踪算法 附上实现的代码地址与已经测试成功的系统 本文代码地址:open_azure ...

最新文章

  1. pandas基于dataframe特定数据列的指定阈值将原dataframe分割成两个dataframe(split dataframe based on column value threshold
  2. 隐藏tabwidgt 用radiogroup来实现tab的切换
  3. 【微信Java开发 --番外篇】错误解析
  4. AI 玩微信跳一跳的正确姿势:跳一跳 Auto-Jump 算法详解
  5. GitStats:Git开发历史统计工具 - liyropt - 博客园
  6. 太阳能电池基本特性实验报告_太阳能电池基本特性研究实验报告的数据处理Ini怎么?太阳能电池基 爱问知识人...
  7. 训练代码_无需一行代码,完成模型训练和部署,这个AI工具开始公测
  8. mysql left join和or_Case:MySQL使用left join的时候or改写成union可以提高效率
  9. 敏捷开发用户故事系列之九:开发与跟进
  10. AC自动机——多个kmp匹配
  11. mongodb 批量插入_MongoDB批量插入– MongoDB插入很多
  12. 网络游戏加速器软件市场现状研究分析-
  13. Guice依赖注入(Scope)
  14. Excel学习日记:L4-资料排序
  15. 【Java实习生】每日10道面试题打卡!
  16. 苹果app退款_app退款理由写什么好?苹果退款理由怎么写才好?
  17. 如何在线打开Xmind文件 — 百度脑图在线工具
  18. 《基于C/S模式的android手机与PC机通信系统的开发》项目
  19. 龙芯与飞腾roadmap
  20. strcmp函数的C语言实现

热门文章

  1. JanusGraph学习笔记
  2. 40套各种风格住宿酒店行业网站html5模板大气商务酒店网站模板度假村酒店官方网站模板旅行酒店宾馆整站模板html5网页静态模板Bootstrap扁平化网站源码css3手机seo自适响应
  3. cocos2d-x学习资源整理(持续更新)
  4. 微软surface屏幕测试软件,Soomal作品 - Microsoft 微软 Surface Book 笔记本电脑屏幕测评报告和色彩校正 [Soomal]...
  5. Wifi密码破解之二:利用wps漏洞穷举PIN码破解wifi密码
  6. 小米r1d安装php,小米路由器 一键安装LLM教程
  7. 开涛传–记京东“首席”架构师张开涛
  8. TopJui 我踩的那些坑
  9. Arduino呼吸灯
  10. vtd xml java_新兴XML处理方法VTD-XML介绍