博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用Camshift算法对指定目标进行跟踪
阅读量:6514 次
发布时间:2019-06-24

本文共 2752 字,大约阅读时间需要 9 分钟。

原理

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 
#include
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
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;}

效果

用摄像头获取视频
直接读取视频

总结:

效果不是太好。可能是没有预处理或者參数设置的不好。
刚開始学习的人。期待大婶知道!

你可能感兴趣的文章
SCOM 2012 SP1服务器上安装和配置Veeam MP for VMware
查看>>
多核编程的四层境界
查看>>
Windows Phone 实用开发技巧(11):让StackPanel中的控件靠右对齐
查看>>
小记如何修改xen模块
查看>>
实时游戏对战引擎Photon
查看>>
C语言位操作控件属性
查看>>
nginx的安装及基本配置,及多个域名服务
查看>>
Servlet访问postgresql数据库并提取数据显示在前端jsp页面
查看>>
不改一行代码定位线上性能问题
查看>>
定义运算符
查看>>
git管理
查看>>
idea演示
查看>>
告别暗黄皮肤变水嫩皮肤的8个小习惯
查看>>
加强Eclipse代码自动提示的方法
查看>>
GNS3-地址重叠环境中部署IPsec
查看>>
exchange online 用户疑问之许可证和用户数据归档
查看>>
QImage Mat IplImage 之间的相互转换
查看>>
使用eclipse与android studio 在开发自定义控件时的区别
查看>>
我的友情链接
查看>>
mysql学习笔记
查看>>