粒子滤波跟踪算法实现的基本步骤如下:
- 初始化步骤:选择目标,计算目标模型颜色直方图,初始化粒子。
- 粒子采样及权重计算:在上一帧目标附近按高斯分布散布粒子,统计每个粒子的颜色直方图。与目标模型颜色直方图对比,根据巴氏距离计算权值,再对权值进行归一化处理。
- 样本重采样:得到粒子权值之后,需要对粒子重新采样。去除权值较小的粒子,用权值较大的粒子代替,更新粒子。
- 目标捕获:根据重采样后的粒子位置权重计算目标位置,完成跟踪。
- 重复步骤2 – 4。
其中主要的步骤是粒子的散布、权值计算和重采样。粒子散布时,一般按照高斯分布进行散布。在算法实现中,使用高斯随机数生成器在目标原始位置上进行坐标偏移,实现粒子的高斯分布。
粒子的权值计算即对比粒子颜色直方图和目标颜色直方图的相似性,算法实现中通过计算直方图之间的巴氏距离来表示直方图的相似性,从而得到粒子的权值。
粒子的重采样的目的在于粒子散布时,粒子的分布并不是足够均匀的,表现为计算的粒子权值有些大有些小。需要对权值较小的粒子重新采样实现粒子权值的均匀分布。算法实现中,用权值较大的粒子取代权值较小的粒子,实现粒子的重采样。
重采样之后得到所有粒子的位置,根据粒子的位置和权值计算目标的位置,实现跟踪。
附代码
// object_track.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<opencv2/opencv.hpp>
#include <iostream>
#include <random>
using namespace std;
using namespace cv;
//随机数生成
std::tr1::mt19937 eng;
std::tr1::normal_distribution<double> dist;
//定义粒子结构
struct Particle{
CvRect currentRectROI;
CvRect previousRectROI;
double wight;
};
//参数定义
#define NUM_OF_PARTICLES 500
#define MOVE_RATIO 50.000
#define SCALE_RATIO 0.001
//选择目标框回调函数
void selectTargetCallback(int event, int x, int y, int flags, void* param);
//计算直方图
CvHistogram* getHistogramFromImageH(IplImage* image);
//散布粒子
void transition(Particle(&particles)[NUM_OF_PARTICLES]);
//显示粒子
void showparticles(IplImage* image, Particle particles[NUM_OF_PARTICLES]);
//计算粒子权重
void getparticleswight(IplImage* imageH, CvHistogram* refHist, Particle(&particles)[NUM_OF_PARTICLES]);
//计算目标位置
void gettarget(Particle(&particles)[NUM_OF_PARTICLES]);
//重采样
void resample(Particle(&particles)[NUM_O