1.引言

这个项目是由俄亥俄州立大学(OSU)一位博士生所写,http://web.engr.oregonstate.edu/~hess/,这位博士在其个人主页上对该项目进行了如下描述: 
Object tracking is a tricky problem. A general, all-purpose object tracking algorithm must deal with difficulties like camera motion, erratic object motion, cluttered backgrounds, and other moving objects. Such hurdles render general image processing techniques an inadequate solution to the object tracking problem. 
Particle filtering is a Monte Carlo sampling approach to Bayesian filtering. It has many uses but has become the state of the art in object tracking. Conceptually, a particle filtering algorithm maintains a probability distribution over the state of the system it is monitoring, in this case, the state -- location, scale, etc. -- of the object being tracked. In most cases, non-linearity and non-Gaussianity in the object's motion and likelihood models yields an intractable filtering distribution. Particle filtering overcomes this intractability by representing the distribution as a set of weighted samples, or particles. Each particle represents a possible instantiation of the state of the system. In other words, each particle describes one possible location of the object being tracked. The set of particles contains more weight at locations where the object being tracked is more likely to be. We can thus determine the most probable state of the object by finding the location in the particle filtering distribution with the highest weight. 
大致翻译如下: 
物体追踪是一个棘手的问题。一个普适的,通用的物体追踪算法必须应对诸如摄像头运动、不稳定物体的追踪、复杂的背景、以及存在其他移动物体等困难的状况。粒子滤波算法是一个采用蒙特卡罗采样进行贝叶斯滤波的方法。这种方法有许多的用途,但它已经成为进行物体追踪最好的方法。从概念上讲,一个粒子滤波算法包含一个被监视系统的状态的概率分布。在本项目中,状态就是指被追踪物体的位置、大小等等。在许多情况下,非线性和非高斯型在物体的运动和相似性建模上会得到一个难以处理的滤波分布。粒子滤波采用将这个分布重新表示为一组加权值,或称为粒子的方法克服了这个困难。每个粒子表示一个可能的系统状态实例。换句话说,每个粒子描述了被追踪物体可能处于的一个方位。一个粒子集包含了被追踪物体最有可能处于的方位。因此,我们可以通过寻找在粒子滤波分布中最大的权重来确定物体最有可能处于的状态。

2.程序流程总述

1.命令行参数处理 -> 
2.设置随机数生成器环境,创建随机数生成器、并且对其初始化。-> 
3.初始化视频句柄 -> 
4.取视频中的一帧进行处理 -> 
1)GRB->HSV 
2)保存当前帧在frames 
3) 判断是否为第一帧, 
若是则, 
(1)忙等用户选定欲跟踪的区域 
(2)计算相关区域直方图 
(3)得到跟踪粒子 
若不是则, 
(1)对每个粒子作变换,并计算每个粒子的权重 
(2)对粒子集合进行归一化 
(3)重新采样粒子 
4)画出粒子所代表的区域 
5.释放图像

3.命令行参数处理

void arg_parse( int argc, char** argv )
{int i = 0;/*extract program name from command line (remove path, if present) */pname = remove_path( argv[0] );/*parse commandline options */while( TRUE ){char* arg_check;int arg = getopt( argc, argv, OPTIONS );if( arg == -1 )break;switch( arg ){/* user asked for help */case 'h':usage( pname );exit(0);break;case 'a':show_all = TRUE;break;/* user wants to output tracking sequence */case 'o':export = TRUE;break;/* user wants to set number of particles */case 'p':if( ! optarg )fatal_error( "error parsing arguments at -%c/n"    /"Try '%s -h' for help.", arg, pname );num_particles = strtol( optarg, &arg_check, 10 );if( arg_check == optarg  ||  *arg_check != '/0' )fatal_error( "-%c option requires an integer argument/n"    /"Try '%s -h' for help.", arg, pname );break;      /* catch invalid arguments */default:fatal_error( "-%c: invalid option/nTry '%s -h' for help.",optopt, pname );}}/* make sure input and output files are specified */if( argc - optind < 1 )fatal_error( "no input image specified./nTry '%s -h' for help.", pname );if( argc - optind > 2 )fatal_error( "too many arguments./nTry '%s -h' for help.", pname );/* record video file name */vid_file = argv[optind];
}

作者使用Getopt这个系统函数对命令行进行解析,-h表示显示帮助,-a表示将所有粒子所代表的位置都显示出来,-o表示输出tracking的帧,-p number进行粒子数的设定,然后再最后指定要处理的视频文件。

4.RGB->HSV变换

IplImage* bgr2hsv( IplImage* bgr )
{
IplImage* bgr32f, * hsv;bgr32f = cvCreateImage( cvGetSize(bgr), IPL_DEPTH_32F, 3 );
hsv = cvCreateImage( cvGetSize(bgr), IPL_DEPTH_32F, 3 );
cvConvertScale( bgr, bgr32f, 1.0 / 255.0, 0 );
cvCvtColor( bgr32f, hsv, CV_BGR2HSV );
cvReleaseImage( &bgr32f );
return hsv;
}

程序现将图像的像素值归一化,然后使用OpenCV中的cvCvtcolor函数将图像从RGB空间转换到HSV空间。

5.设定随机数

gsl_rng_env_setup();//setup the enviorment of random number generator 
rng = gsl_rng_alloc( gsl_rng_mt19937 );//create a random number generator 
gsl_rng_set( rng, time(NULL) );//initializes the random number generator. 
作者使用GSL库进行随机数的产生,GSL是GNU的科学计算库,其中手册中random部分所述进行随机数生成有三个步骤: 
随机数生成器环境建立,随机数生成器的创建,随机数生成器的初始化。

6.计算选定区域直方图

/*Computes a reference histogram for each of the object regions defined bythe user@param frame video frame in which to compute histograms; should have beenconverted to hsv using bgr2hsv in observation.h@param regions regions of /a frame over which histograms should be computed@param n number of regions in /a regions@param export if TRUE, object region images are exported@return Returns an /a n element array of normalized histograms correspondingto regions of /a frame specified in /a regions.
*/
histogram** compute_ref_histos( IplImage* frame, CvRect* regions, int n )
{histogram** histos = malloc( n * sizeof( histogram* ) );IplImage* tmp;int i;/* extract each region from frame and compute its histogram */for( i = 0; i < n; i++ ){cvSetImageROI( frame, regions[i] );//set the region of interesttmp = cvCreateImage( cvGetSize( frame ), IPL_DEPTH_32F, 3 );cvCopy( frame, tmp, NULL );cvResetImageROI( frame );//free the ROIhistos[i] = calc_histogram( &tmp, 1 );//calculate the hisrogramnormalize_histogram( histos[i] );//Normalizes a histogram so all bins sum to 1.0cvReleaseImage( &tmp );}return histos;
}

程序中先设置了一个类型为histogram的指向指针的指针,是histogram指针数组的指针,这个数组是多个选定区域的直方图数据存放的位置。然后对于每一个用户指定的区域,在第一帧中都进行了ROI区域设置,通过对ROI区域的设置取出选定区域,交给函数calc_histogram计算出直方图,并使用normalize_histogram对直方图进行归一化。 
计算直方图的函数详解如下:

/*Calculates a cumulative histogram as defined above for a given arrayof images@param img an array of images over which to compute a cumulative histogram;each must have been converted to HSV colorspace using bgr2hsv()@param n the number of images in imgs@return Returns an un-normalized HSV histogram for /a imgs
*/
histogram* calc_histogram( IplImage** imgs, int n )
{IplImage* img;histogram* histo;IplImage* h, * s, * v;float* hist;int i, r, c, bin;histo = malloc( sizeof(histogram) );histo->n = NH*NS + NV;hist = histo->histo;memset( hist, 0, histo->n * sizeof(float) );for( i = 0; i < n; i++ ){/* extract individual HSV planes from image */img = imgs[i];h = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );s = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );v = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );cvCvtPixToPlane( img, h, s, v, NULL );/* increment appropriate histogram bin for each pixel */for( r = 0; r < img->height; r++ )for( c = 0; c < img->width; c++ ){bin = histo_bin( pixval32f( h, r, c ),pixval32f( s, r, c ),pixval32f( v, r, c ) );hist[bin] += 1;}cvReleaseImage( &h );cvReleaseImage( &s );cvReleaseImage( &v );}return histo;
}

这个函数将h、s、 v分别取出,然后以从上到下,从左到右的方式遍历以函数histo_bin的评判规则放入相应的bin中(很形象的)。函数histo_bin的评判规则详见下图: 
|----|----|----|。。。。|----|------|------|。。。。|-------| 
      1NH      2NH       3NH                    NS*NH    NS*NH+1    NS*NH+2                     NS*NH+NV

7.初始化粒子集

/*
Creates an initial distribution of particles at specified locations@param regions an array of regions describing player locations around
which particles are to be sampled
@param histos array of histograms describing regions in /a regions
@param n the number of regions in /a regions
@param p the total number of particles to be assigned@return Returns an array of /a p particles sampled from around regions in
/a regions
*/
particle* init_distribution( CvRect* regions, histogram** histos, int n, int p)
{
particle* particles;
int np;
float x, y;
int i, j, width, height, k = 0;particles = malloc( p * sizeof( particle ) );
np = p / n;/* create particles at the centers of each of n regions */
for( i = 0; i < n; i++ )
{
width = regions[i].width;
height = regions[i].height;
x = regions[i].x + width / 2;
y = regions[i].y + height / 2;
for( j = 0; j < np; j++ )
{
particles[k].x0 = particles[k].xp = particles[k].x = x;
particles[k].y0 = particles[k].yp = particles[k].y = y;
particles[k].sp = particles[k].s = 1.0;
particles[k].width = width;
particles[k].height = height;
particles[k].histo = histos[i];
particles[k++].w = 0;
}
}/* make sure to create exactly p particles */
i = 0;
while( k < p )
{
width = regions[i].width;
height = regions[i].height;
x = regions[i].x + width / 2;
y = regions[i].y + height / 2;
particles[k].x0 = particles[k].xp = particles[k].x = x;
particles[k].y0 = particles[k].yp = particles[k].y = y;
particles[k].sp = particles[k].s = 1.0;
particles[k].width = width;
particles[k].height = height;
particles[k].histo = histos[i];
particles[k++].w = 0;
i = ( i + 1 ) % n;
}return particles;
}

程序中的变量np是指若有多个区域n,则一个区域内的粒子数为p/n,这样粒子的总数为p。然后程序对每个区域(n个)中p/n个粒子进行初始化,三个位置坐标都为选定区域的中点,比例都为1,宽度和高度为选定区域的高度。然后又跑了个循环确定p个粒子被初始化。

8.位置可能性确定

/*Computes the likelihood of there being a player at a given location inan image@param img image that has been converted to HSV colorspace using bgr2hsv()@param r row location of center of window around which to compute likelihood@param c col location of center of window around which to compute likelihood@param w width of region over which to compute likelihood@param h height of region over which to compute likelihood@param ref_histo reference histogram for a player; must have beennormalized with normalize_histogram()@return Returns the likelihood of there being a player at location(/a r, /a c) in /a img
*/
float likelihood( IplImage* img, int r, int c,int w, int h, histogram* ref_histo )
{IplImage* tmp;histogram* histo;float d_sq;/* extract region around (r,c) and compute and normalize its histogram */cvSetImageROI( img, cvRect( c - w / 2, r - h / 2, w, h ) );tmp = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 3 );cvCopy( img, tmp, NULL );cvResetImageROI( img );histo = calc_histogram( &tmp, 1 );cvReleaseImage( &tmp );normalize_histogram( histo );/* compute likelihood as e^{/lambda D^2(h, h^*)} */d_sq = histo_dist_sq( histo, ref_histo );free( histo );return exp( -LAMBDA * d_sq );
}

程序首先取出对相关粒子表示的区域,然后计算其直方图,并且归一化。将这个直方图和原来用户选定区域的直方图传入函数histo_dist_sq进行比较,最后返回e^(-Lambda*d_sq)返回,成为这个粒子的权重。 
函数histo_dist_sq的实现如下:

/*Computes squared distance metric based on the Battacharyya similaritycoefficient between histograms.@param h1 first histogram; should be normalized@param h2 second histogram; should be normalized@return Returns a squared distance based on the Battacharyya similaritycoefficient between /a h1 and /a h2
*/
float histo_dist_sq( histogram* h1, histogram* h2 )
{float* hist1, * hist2;float sum = 0;int i, n;n = h1->n;hist1 = h1->histo;hist2 = h2->histo;/*According the the Battacharyya similarity coefficient,D = /sqrt{ 1 - /sum_1^n{ /sqrt{ h_1(i) * h_2(i) } } }*/for( i = 0; i < n; i++ )sum += sqrt( hist1[i]*hist2[i] );return 1.0 - sum;
}

采用统计学上的巴氏距离Bhattacharyya distance,根据wiki的描述, Bhattacharyya distance 描述的是两个离散概率分布的相似性,它通常在分类操作中被用来度量不同类型的可分离性,也就是说这个距离算式就是评定相似度的。

9.粒子集合变换

/*Samples a transition model for a given particle@param p a particle to be transitioned@param w video frame width@param h video frame height@param rng a random number generator from which to sample@return Returns a new particle sampled based on <EM>p</EM>'s transitionmodel
*/
particle transition( particle p, int w, int h, gsl_rng* rng )
{float x, y, s;particle pn;/* sample new state using second-order autoregressive dynamics */x = A1 * ( p.x - p.x0 ) + A2 * ( p.xp - p.x0 ) +B0 * gsl_ran_gaussian( rng, TRANS_X_STD ) + p.x0;pn.x = MAX( 0.0, MIN( (float)w - 1.0, x ) );y = A1 * ( p.y - p.y0 ) + A2 * ( p.yp - p.y0 ) +B0 * gsl_ran_gaussian( rng, TRANS_Y_STD ) + p.y0;pn.y = MAX( 0.0, MIN( (float)h - 1.0, y ) );s = A1 * ( p.s - 1.0 ) + A2 * ( p.sp - 1.0 ) +B0 * gsl_ran_gaussian( rng, TRANS_S_STD ) + 1.0;pn.s = MAX( 0.1, s );pn.xp = p.x;pn.yp = p.y;pn.sp = p.s;pn.x0 = p.x0;pn.y0 = p.y0;pn.width = p.width;pn.height = p.height;pn.histo = p.histo;pn.w = 0;return pn;
}

程序使用动态二阶自回归模型作为基本变换思路,变换的对象有坐标x,坐标y,和比例s。变换的x和y要符合在width和height之内的条件。

10.粒子集重新采样

/*Re-samples a set of particles according to their weights to produce anew set of unweighted particles@param particles an old set of weighted particles whose weights have beennormalized with normalize_weights()@param n the number of particles in /a particles@return Returns a new set of unweighted particles sampled from /a particles
*/
particle* resample( particle* particles, int n )
{particle* new_particles;int i, j, np, k = 0;qsort( particles, n, sizeof( particle ), &particle_cmp );new_particles = malloc( n * sizeof( particle ) );for( i = 0; i < n; i++ ){np = cvRound( particles[i].w * n );for( j = 0; j < np; j++ ){new_particles[k++] = particles[i];if( k == n )goto exit;}}while( k < n )new_particles[k++] = particles[0];exit:return new_particles;
}

程序先使用C标准库中的qsort排序函数,按照权重,由大到小将原粒子集排序。然后将权重大的在新的粒子集中分配的多一点。

11.权重归一化

/*Normalizes particle weights so they sum to 1@param particles an array of particles whose weights are to be normalized@param n the number of particles in /a particles
*/
void normalize_weights( particle* particles, int n )
{float sum = 0;int i;for( i = 0; i < n; i++ )sum += particles[i].w;for( i = 0; i < n; i++ )particles[i].w /= sum;
}

基于partical filter的跟踪相关推荐

  1. 基于MeanShift的目标跟踪算法及实现

    from: http://blog.csdn.net/jinshengtao/article/details/30258833 一.简介 首先扯扯无参密度估计理论,无参密度估计也叫做非参数估计,属于数 ...

  2. OpenCV基于均值漂移的跟踪的实例(附完整代码)

    OpenCV基于均值漂移的跟踪的实例 OpenCV基于均值漂移的跟踪的实例 OpenCV基于均值漂移的跟踪的实例 #include "opencv2/core/utility.hpp&quo ...

  3. java 天猫模拟登陆_基于servlet+filter+反射模拟实现天猫首页的后端

    前言:为了深入web原理,本项目没有使用框架,主要描述了从请求到页面展现的思路,详情请见文末的具体项目 一.为什么要用filter?直接servlet实现不就行了 因为天猫这样的项目需要很多servl ...

  4. adc0832对光电二极管进行数据采集_一种基于光电二极管的麦克风跟踪检测电路的制作方法...

    本实用新型涉及一种基于光电二极管的麦克风跟踪检测电路,属于应用电子技术领域. 背景技术: 随着互联网的发展,语音交互应用正在日益变多,近几年视频直播.网络直播.K歌软件都发展得很快,也推高了麦克风的销 ...

  5. 基于MeanShift的目标跟踪算法及实现(转载)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/jinshengtao/article/details/30258833 这次将介绍基于MeanShi ...

  6. 基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统)

    基于meanshift的手势跟踪与电脑鼠标控制(手势交互系统) zouxy09@qq.com http://blog.csdn.net/zouxy09 一年多前开始接触计算机视觉这个领域的时候,年幼无 ...

  7. 最大功率点跟踪_华北电力大学颜湘武团队特稿:基于变功率点跟踪和超级电容器储能协调控制的双馈风电机组一次调频策略...

    武汉加油 风雨同行 共克时艰 点击下面标题,了解通知详情第九届电工技术前沿问题学术论坛征文通知团队介绍 颜湘武,博士,教授,博士生导师,"分布式储能与微网"河北省重点实验室副主任, ...

  8. 浏览器禁用Cookie,基于Cookie的会话跟踪机制失效的解决的方法

    当浏览器禁用Cookies时.基于Cookie的会话跟踪机制就会失效.解决的方法是利用URL重写机制跟踪用户会话. 在使用URL重写机制的时候须要注意.为了保证会话跟踪的正确性,全部的链接和重定向语句 ...

  9. 使用Minifly打造基于视觉感知的跟踪无人机

    摘自:https://www.cnblogs.com/kryo/p/11278565.html 使用Minifly打造基于视觉感知的跟踪无人机 前言:本文介绍一种可行的解决方案来实现基于视觉感知的跟踪 ...

最新文章

  1. numpy向量加一个常数=向量中的每个值加上这个常数,最后返回一个同维的向量
  2. Redis(七)Redis的噩梦:阻塞
  3. 是MPEG没有未来,还是未来不需要MPEG
  4. matlab在linux下面的相对路径的写法
  5. ios解锁动态图片_iOS 苹果开机启动的 滑动来解锁动画
  6. 1295. 统计位数为偶数的数字
  7. 厉害插件_2个相见恨晚的浏览器插件,让你的工作效率提升100%
  8. (TOJ1248)Encoding
  9. ECshop sina
  10. 面向对象第一单元(表达式求导)总结体会
  11. [渝粤教育] 西南科技大学 行政法学与行政诉讼法学 在线考试复习资料(1)
  12. js遍历(js遍历json对象)
  13. Photoshop CS4 卡通角色的设计与绘制(2)
  14. python的对文档密码的简单破解
  15. DGIOT物联网平台简介
  16. java打印 X XX XXX XXXX
  17. HTTP网络连接相关知识整理(三):网络错误异常
  18. FusionCompute
  19. 浪潮服务器外接显示器,浪潮服务器简易配置手册.doc
  20. java设计模式系列的7大设计原则

热门文章

  1. Android群英传知识点回顾——第十章:Android性能优化
  2. 感叹号在c语言的作用,第二:感叹号在公式中的用途 感叹号在公式里的应用
  3. 【心情】今天看了日全食。。。
  4. 灰色关联投影法python_灰色关联投影法(讲座).doc
  5. 文献笔记01-全国计算机等级考试报名系统关键环节设计
  6. 【从零开始学用OpenCV】Day1 环境配置与搭建
  7. RVS消防双绞线的介绍
  8. NNDL 作业9:分别使用numpy和pytorch实现BPTT
  9. 在国内企业做数据治理,建议您考个DAMA-CDGA/CDGP证书
  10. 区块链溯源:如何实现全球商品的溯源?