用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算法对指定目标进行跟踪

时间: 2024-10-05 14:14:27

用Camshift算法对指定目标进行跟踪的相关文章

OpenCV:利用Camshift算法进行彩色目标的跟踪

<span style="font-size:14px;">#include <opencv\cv.h> #include <opencv\highgui.h> #include <stdio.h> #include <ctype.h> IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0; CvHistogram

【计算机视觉】借助图像直方图来检测特定物(MeanShift、CamShift算法)

直方图引入 直方图是一个简单的表,它给出了一幅图像或一组图像中拥有给定数值的像素数量.因此,灰度图像的直方图有256个条目(或称为容器).0号容器给出值为0的像素数目,1号容器给出值为1的像素个数,以此类推. 直方图反投影 直方图是图像内容的一个重要特性.如果一幅图像的区域中显示的是一种独特的纹理或是一个独特的物体,那么这个区域的直方图可以看做一个概率函数,它给出的是某个像素属于该纹理或物体的概率.这使得我们可以借助图像的直方图来检测特定的内容. 反投影直方图的方法是一种把目标概率分布映射到观测

c++ 使用算法时确保目标区间足够大

/************************************************************************* * * 无论何时,如果使用的算法需要指定一个目标区间,要么必须确保区间足够大 * 要么确保它会随着算法的运行而增大. * 要在算法执行过程中增大目标区间,请使用插入型的迭代器,如ostream_stream, * back_inserter,front_inserter,inserter 返回的迭代器. * ********************

SqlBulkCopy 来自数据源的 String 类型的给定值不能转换为指定目标列的类型 bit

使用SqlBulkCopy批量插入,可以快速对大批量的数量插入,性能非常好 在使用时出现“来自数据源的 String 类型的给定值不能转换为指定目标列的类型 bit”异常 为DataTable与要插入的数据表字段位置不一样所至 DataTable与要插入的数据表要字段名,位置,数据类型都一至才可 示例,使用使用SqlBulkCopy插入多个表 public bool BatchInsertUniqeCode(DataTable uniqueCodeProduceContrastDt,DataTa

[ jquery 效果 fadeTo([speed,[easing],[fn]]) ] 此方法用于通过调整不透明度的变化至指定目标来实现所有匹配元素的淡入效果,并在动画完成后可选地触发一个回调函数

此方法用于通过调整不透明度的变化至指定目标来实现所有匹配元素的淡入效果,并在动画完成后可选地触发一个回调函数 实例: <html lang='zh-cn'> <head> <title>Insert you title</title> <meta http-equiv='description' content='this is my page'> <meta http-equiv='keywords' content='keyword1,

saltstack的探索-salt指定目标和分组

一.探讨一下,如何针对指定的minion id来执行 先了解官网文档的targeting这一节的内容: Targeting Salt allows for minions to be targeted based on a wide range of criteria. The default targeting system uses globular expressions to match minions, hence if there are minions named larry1, 

使用sqlbulkcopy报错:1 DataSet 不支持 System.Nullable&lt;&gt;,2.来自数据源的 String 类型的给定值不能转换为指定目标列的类型 nvarchar。

第一个问题, 解决方法:dt.addcolunms("名字","类型"),类型不能为typeof( int?),typeof(datetime?)等可空值类型.字符串可以.所以可空值类型改成不可空即可. 第二问题, 解决方法: bulkCopy.WriteToServer(dt);先检查dt的列类型是不是不对?,如果没问题,再检查这个dt的列的顺序和数据库列的顺序保持一致. 本人遇到这两个问题就这样解决了.有朋友可能会说,我datatable的列名不就是字段名吗,为

学习笔记:vsphere6 迁移物理机,指定目标报错

原因: Esxi已经分配给vCenter管理,所以这里不能直接使用Esxi的IP 解决: 填入vCenter的ip和user,password 即可

算法生成指定数目的随机数

package text; import java.util.Scanner; public class random { public static void main(String[] args) { int a=13, b=35,m=87,Xo=19; int z=Xo; System.out.print("请输入生成随机数的个数:"); Scanner cin1=new Scanner(System.in); int j=cin1.nextInt(); int q=0; for