目标跟踪之粒子滤波

转载自:https://blog.csdn.net/u014568921/article/details/46574017

基本思想

所谓粒子滤波就是指:通过寻找一组在状态空间中传播的随机样本来近似的表示概率密度函数,用样本均值代替积分运算,进而获得系统状态的最小方差估计的过程,这些样本被形象的称为“粒子”,故而叫粒子滤波。采用数学语言描述如下: 对于平稳的随机过程, 假定k - 1 时刻系统的后验概率密度为p ( xk-1 zk-1 ) , 依据一定原则选取n 个随机样本点, k 时刻获得测量信息后, 经过状态和时间更新过程, n 个粒子的后验概率密度可近似为p ( xk zk ) 。随着粒子数目的增加, 粒子的概率密度函数逐渐逼近状态的概率密度函数, 粒子滤波估计即达到了最优贝叶斯估计的效果。

粒子滤波算法摆脱了解决非线性滤波问题时随机量必须满足高斯分布的制约条件, 并在一定程度上解决了粒子数样本匮乏问题, 因此近年来该算法在许多领域得到成功应用。


贝叶斯滤波

动态系统的状态空间模型可描述为

其中f(),h()分别为状态转移方程与观测方程,xk为系统状态,yk为观测值,uk为过程噪声,vk为观测噪声。为了描述方便,用Xk=x0:k={x0,x1,…,xk}与Yk=y0:k={y0,y1,…,yk}分别表示0到k时刻所有的状态与观测值。在处理目标跟踪问题时,通常假设目标的状态转移过程服从一阶马尔可夫模型,即当前时刻的状态xk只与上一时刻的状态xk-1有关。另外一个假设为观测值相互独立,即观测值yk只与k时刻的状态xk有关。

贝叶斯滤波为非线性系统的状态估计问题提供了一种基于概率分布形式的解决方案。贝叶斯滤波将状态估计视为一个概率推理过程,即将目标状态的估计问题转换为利用贝叶斯公式求解后验概率密度p(Xk|Yk)或滤波概率密度p(xk|Yk),进而获得目标状态的最优估计。贝叶斯滤波包含预测和更新两个阶段,预测过程利用系统模型预测状态的先验概率密度,更新过程则利用最新的测量值对先验概率密度进行修正,得到后验概率密度。

假设已知k-1时刻的概率密度函数为p(xk-1|Yk-1),贝叶斯滤波的具体过程如下:

(1) 预测过程,由p(xk-1|Yk-1)得到p(xk|Yk-1):

p(xk,xk-1|Yk-1)=p(xk|xk-1,Yk-1)p(xk-1|Yk-1)       

当给定xk-1时,状态xk与Yk-1相互独立,因此

p(xk,xk-1|Yk-1)=p(xk|xk-1)p(xk-1|Yk-1)              

上式两端对xk-1积分,可得Chapman-Komolgorov方程


(2) 更新过程,由p(xk|Yk-1)得到p(xk|Yk):

获取k时刻的测量yk后,利用贝叶斯公式对先验概率密度进行更新,得到后验概率


假设yk只由xk决定,即

p(yk|xk,Yk-1)=p(yk|xk)                      

因此

                     

其中,p(yk|Yk-1)为归一化常数

               

贝叶斯滤波以递推的形式给出后验(或滤波)概率密度函数的最优解。目标状态的最优估计值可由后验(或滤波)概率密度函数进行计算。通常根据极大后验(MAP)准则或最小均方误差(MMSE)准则,将具有极大后验概率密度的状态或条件均值作为系统状态的估计值,即

                                                            

贝叶斯滤波需要进行积分运算,除了一些特殊的系统模型(如线性高斯系统,有限状态的离散系统)之外,对于一般的非线性、非高斯系统,贝叶斯滤波很难得到后验概率的封闭解析式。因此,现有的非线性滤波器多采用近似的计算方法解决积分问题,以此来获取估计的次优解。在系统的非线性模型可由在当前状态展开的线性模型有限近似的前提下,基于一阶或二阶Taylor级数展开的扩展Kalman滤波得到广泛应用。在一般情况下,逼近概率密度函数比逼近非线性函数容易实现。据此,Julier与Uhlmann提出一种Unscented Kalman滤波器,通过选定的sigma点来精确估计随机变量经非线性变换后的均值和方差,从而更好的近似状态的概率密度函数,其理论估计精度优于扩展Kalman滤波。获取次优解的另外一中方案便是基于蒙特卡洛模拟的粒子滤波器。


蒙特卡洛近似思想

蒙特卡洛积分是一项用随机釆样来估算积分值的技术,简单说就是以某事件出现的频率来指代该事件的概率。因此在滤波过程中,需要用到概率如P(x)的地方,一概对变量x采样,以大量采样及其相应的权值来近似表示P(x)。

然而,在计算机问世以前,随机试验却受到一定限制,这是因为要使计算结果的准确度足够高,需要进行的试验次数相当大。因此人们都认为随机试验要用人工进行冗长的计算,这实际上是不可能的。

随着电子计算机的出现,利用电子计算机可以实现大量的随机抽样试验,使得用随机试验方法解决实际问题才有了能。

它的基本思想是:为了求解数学、物理、工程技术以及生产管理等方面的问题,首先建立一个概率模型或随机过程,使它的参数等于问题的解,然后通过对模型或过程的观察或抽样试验来计算所求参数的统计特征,最后给出所求解的近似

值,而解的精确度可用估计值的标准误差来表示。 

粒子滤波算法的核心思想便是利用一系列随机样本的加权和表示后验概率密度,通过求和来近似积分操作。


重要性采样 (Importance Sampling)

这是一种蒙特卡洛方法(Monte Carlo)。在有限的采样次数内,尽量让采样点覆盖对积分贡献很大的点。该方法目的并不是用来产生一个样本的,而是求一个函数的定积分的,只是因为该定积分的求法是通过对另一个叫容易采集分布的随机采用得到的。


序贯重要性采样(Sequential Importance Sainpling,SIS)

在粒子滤波算法中重采样的基本思想是抛弃那些对估计系统后验概率密度权值较小的粒子,通过复制权值较大的粒子来代替它们,进行重釆样有多种方法,常见的有多项式重釆样、系统重采样、分层抽样、残差抽样等,目前最为常用的重采样方法就是序贯重要性釆样。
在基于重要性重采样的蒙特卡洛模拟方法中,估计后验滤波概率需要利用所有的观测数据,每次新的观测数据来到都需要重新计算整个状态序列的重要性权值。序贯重要性釆样作为粒子滤波的基础,它将统计学的序贯分析方法应用到蒙特卡洛方法中,其主要思想就是递归的计算重采样粒子,通过保留以前所有采样时刻的粒子状态以保持采样粒子的继承性,从而实现后验滤波概率密度的递归估计。

基于序贯蒙特卡洛模拟方法的粒子滤波算法存在采样粒子权值退化问题以及计算量过大的问题,在实际计算中,经过数次迭代,只有少数粒子的权值较大,其余粒子的权值较小甚至可以忽略不计,粒子权值的方差随着时间的推移而增大,状态空间中的有效粒子数减少,随着无效粒子数量的增加,使得大量的计算消耗在对估计后验滤波概率分布几乎不起作用的粒子上,使得计算量增大且估计性能下降。

SIS算法的具体步骤如下:

1.系统初始化

k = 0,随机提取N个样本点


并给采样粒子赋予相应的初始权值为



2.抽取N个样本

在时刻k=1,2,…,L通过随机釆样的方法从以下分布抽取N个样本

3.逐点计算对应的p(xk|xk-1)和p(zk|xk)


4.更新权值

该时刻的采样粒子点的权值按下式计算



3.粒子权值归一化




权值退化

粒子滤波的核心思想是系统随机釆样与重要性重釆样的相加,粒子滤波首先根据系统在t时刻的系统状态x(t)和系统的概率分布生成大量的采样,这些采样就称之为粒子,那么这些采样在状态空间中的分布实际上就是x(t)的概率分布了,其后根据系统状态转移方程就可以对每一个粒子得到一个预测粒子,所有的预测粒子就代表系统所涉及的参数化东西。在滤波的预估计阶段,随机进行粒子采样,采样完成后根据特征相似度计算每个粒子的重要性,并根据重要性赋予粒子相应的权值,因此粒子滤波方法较之蒙特卡洛方法计算量较小,但是这种方法严重依赖于对初始状态的估计,随着迭代算法的进行,在经过数次迭代后其粒子采样的分配权重的方差会随着时间的推移而不断增大,除少数粒子以外的其他所有粒子只具有微小的权值并最终趋向于0,而少数粒子的权值会变的越来越大,随着采样过程的继续,最终所产生的粒子只是最初一小部分粒子权值的衍生,采样粒子代表的系统就会失去多样性,而当前系统的后验概率密度分布情况不能够有效的表示,我们将其称之为权值退化问题。

由于采样粒子权值退化问题在基于序贯重要性采样的粒子滤波算法中广泛存在,在经过数次迭代之后,许多粒子的权值变得很小,大量的计算浪费在小权值的粒子上,从而影响系统效率。目前降低该问题影响的最有效方法是选择重要性函数和采用重采样方法


重要性函数的选择

在重要性概率密度函数选择中融入系统最新的观测信息,通过选取好的重要性概率密度函数来有效抑制退化问题。

重采样

通过对粒子及其相应权值表示的概率密度函数进行重新采样,形成一个新的粒子集,该粒子集构成后验密度离散近似的一个经验分布,在釆样总数保持不变的情况下,权值较大的样本被多次复制,从而实现重釆样过程,通过引入重釆样技术,增加了权值较大的粒子数,在一定程度上能够有效解决粒子权值退化问题。重采样过程是以牺牲系统鲁棒性和计算效率来解决粒子权值退化问题的,并不是所有状态下的粒子都需要进行重采样,因此,我们需要进一步研究粒子权值的退化程度如何进行准确度量,并对粒子是否需要重采样进行有效判断。

重新采样获得的样本可以认为是一系列独立同分布的样本,其权重是一样的,均设为1/N。


采样贫乏

由于包含了大量重复的粒子(这些粒子具有高权值被多次选中),重采样导致了粒子多样性的丧失,此类问题在小噪声的环境下更加突出。事实上如果系统噪声非常小的话,所有粒子会在几次迭代之后崩塌为一个单独的粒子。

经典粒子滤波算法步骤

1.初始化:

取k=0,按p(x0)抽取N个样本点,i=1,…,N。

2.重要性采样:

,其中i=1,…,N。

3.计算权值:


若采用一步转移后验状态分布,该式可简化为

4.归一化权值:

t=   

=/t

5.重采样:根据各自归一化权值的大小复制/舍弃样本,得到N个近似服从分布的样本。令=1/N,i=1,…,N。

6.输出结果:算法的输出是粒子集,用它可以近似表示后验概率和函数的期望



7.K=K+1,重复2步至6步。


粒子滤波其实质是利用一系列随机抽取的样本,也就是粒子,来替代状态的后验概率分布。当粒子的个数变得足够大时,通过这样的随机抽样方法就可以得到状态后验分布很好的近似。





  
  
  1. <span style= "font-size:18px;">function ParticleEx1
  2. % Particle filter example, adapted from Gordon, Salmond, and Smith paper.
  3. x = 0. 1; % initial state
  4. Q = 1; % process noise covariance
  5. R = 1; % measurement noise covariance
  6. tf = 50; % simulation length
  7. N = 100; % number of particles in the particle filter
  8. xhat = x;
  9. P = 2;
  10. xhatPart = x;
  11. % Initialize the particle filter.
  12. for i = 1 : N
  13. xpart(i) = x + sqrt(P) * randn;
  14. end
  15. xArr = [ x];
  16. yArr = [ x^ 2 / 20 + sqrt(R) * randn];
  17. xhatArr = [ x];
  18. PArr = [P];
  19. xhatPartArr = [xhatPart];
  20. close all;
  21. for k = 1 : tf
  22. % System simulation
  23. x = 0. 5 * x + 25 * x / ( 1 + x^ 2) + 8 * cos( 1.2*(k- 1)) + sqrt(Q) * randn;%状态方程
  24. y = x^ 2 / 20 + sqrt(R) * randn;%观测方程
  25. % Extended Kalman filter
  26. F = 0. 5 + 25 * ( 1 - xhat^ 2) / ( 1 + xhat^ 2)^ 2;
  27. P = F * P * F ' + Q;
  28. H = xhat / 10;
  29. K = P * H' * (H * P * H ' + R)^(-1);
  30. xhat = 0.5 * xhat + 25 * xhat / (1 + xhat^2) + 8 * cos(1.2*(k-1));%预测
  31. xhat = xhat + K * (y - xhat^2 / 20);%更新
  32. P = (1 - K * H) * P;
  33. % Particle filter
  34. for i = 1 : N
  35. xpartminus(i) = 0.5 * xpart(i) + 25 * xpart(i) / (1 + xpart(i)^2) + 8 * cos(1.2*(k-1)) + sqrt(Q) * randn;
  36. ypart = xpartminus(i)^2 / 20;
  37. vhat = y - ypart;%观测和预测的差
  38. q(i) = (1 / sqrt(R) / sqrt(2*pi)) * exp(-vhat^2 / 2 / R);
  39. end
  40. % Normalize the likelihood of each a priori estimate.
  41. qsum = sum(q);
  42. for i = 1 : N
  43. q(i) = q(i) / qsum;%归一化权重
  44. end
  45. % Resample.
  46. for i = 1 : N
  47. u = rand; % uniform random number between 0 and 1
  48. qtempsum = 0;
  49. for j = 1 : N
  50. qtempsum = qtempsum + q(j);
  51. if qtempsum >= u
  52. xpart(i) = xpartminus(j);
  53. break;
  54. end
  55. end
  56. end
  57. % The particle filter estimate is the mean of the particles.
  58. xhatPart = mean(xpart);
  59. % Plot the estimated pdf' s at a specific time.
  60. if k == 20
  61. % Particle filter pdf
  62. pdf = zeros( 81, 1);
  63. for m = - 40 : 40
  64. for i = 1 : N
  65. if ( m <= xpart(i)) && (xpart(i) < m+ 1)
  66. pdf( m+ 41) = pdf( m+ 41) + 1;
  67. end
  68. end
  69. end
  70. figure;
  71. m = - 40 : 40;
  72. plot( m, pdf / N, 'r');
  73. hold;
  74. title( 'Estimated pdf at k=20');
  75. disp([ 'min, max xpart(i) at k = 20: ', num2str(min(xpart)), ', ', num2str(max(xpart))]);
  76. % Kalman filter pdf
  77. pdf = ( 1 / sqrt(P) / sqrt( 2*pi)) .* exp(-( m - xhat).^ 2 / 2 / P);
  78. plot( m, pdf, 'b');
  79. legend( 'Particle filter', 'Kalman filter');
  80. end
  81. % Save data in arrays for later plotting
  82. xArr = [xArr x];
  83. yArr = [yArr y];
  84. xhatArr = [xhatArr xhat];
  85. PArr = [PArr P];
  86. xhatPartArr = [xhatPartArr xhatPart];
  87. end
  88. t = 0 : tf;
  89. %figure;
  90. %plot(t, xArr);
  91. %ylabel( 'true state');
  92. figure;
  93. plot(t, xArr, 'b.', t, xhatArr, 'k-', t, xhatArr- 2* sqrt(PArr), 'r:', t, xhatArr+ 2* sqrt(PArr), 'r:');
  94. axis([ 0 tf - 40 40]);
  95. set(gca, 'FontSize', 12); set(gcf, 'Color', 'White');
  96. xlabel( 'time step'); ylabel( 'state');
  97. legend( 'True state', 'EKF estimate', '95% confidence region');
  98. figure;
  99. plot(t, xArr, 'b.', t, xhatPartArr, 'k-');
  100. set(gca, 'FontSize', 12); set(gcf, 'Color', 'White');
  101. xlabel( 'time step'); ylabel( 'state');
  102. legend( 'True state', 'Particle filter estimate');
  103. xhatRMS = sqrt((norm(xArr - xhatArr))^ 2 / tf);
  104. xhatPartRMS = sqrt((norm(xArr - xhatPartArr))^ 2 / tf);
  105. disp([ 'Kalman filter RMS error = ', num2str(xhatRMS)]);
  106. disp([ 'Particle filter RMS error = ', num2str(xhatPartRMS)]); < /span>






   
   
  1. /** @file
  2. Definitions related to tracking with particle filtering
  3. @author Rob Hess
  4. @version 1.0.0-20060307
  5. */
  6. #ifndef PARTICLES_H
  7. #define PARTICLES_H
  8. /******************************* Definitions *********************************/
  9. /* standard deviations for gaussian sampling in transition model */
  10. #define TRANS_X_STD 5.0
  11. #define TRANS_Y_STD 5.0
  12. #define TRANS_S_STD 0.001
  13. /* autoregressive dynamics parameters for transition model */
  14. #define A1 2.0
  15. #define A2 -1.0
  16. #define B0 1.0000
  17. /* number of bins of HSV in histogram */
  18. #define NH 10
  19. #define NS 10
  20. #define NV 10
  21. /* max HSV values */
  22. #define H_MAX 360.0
  23. #define S_MAX 1.0
  24. #define V_MAX 1.0
  25. /* low thresholds on saturation and value for histogramming */
  26. #define S_THRESH 0.1
  27. #define V_THRESH 0.2
  28. /* distribution parameter */
  29. #define LAMBDA 20
  30. #ifndef MIN
  31. # define MIN(a,b) ((a) > (b) ? (b) : (a))
  32. #endif
  33. #ifndef MAX
  34. # define MAX(a,b) ((a) < (b) ? (b) : (a))
  35. #endif
  36. //typedef unsigned char BYTE;
  37. class particle_filter
  38. {
  39. private:
  40. typedef struct Rect
  41. {
  42. int leftupx;
  43. int leftupy;
  44. int width;
  45. int height;
  46. Rect(){}
  47. Rect( int X, int Y, int W, int H)
  48. :leftupx(X), leftupy(Y), width(W), height(H)
  49. {}
  50. }
  51. Rect;
  52. struct Hsv
  53. {
  54. double H; //0-360
  55. double s; //0-1
  56. double v; //0-1
  57. };
  58. /**
  59. An HSV histogram represented by NH * NS + NV bins. Pixels with saturation
  60. and value greater than S_THRESH and V_THRESH fill the first NH * NS bins.
  61. Other, "colorless" pixels fill the last NV value-only bins.
  62. */
  63. typedef struct histogram {
  64. float histo[NH*NS + NV]; /**< histogram array */
  65. int n; /**< length of histogram array */
  66. ~histogram()
  67. {
  68. //if (this)
  69. // delete this;
  70. }
  71. } histogram;
  72. /******************************* Structures **********************************/
  73. /**
  74. A particle is an instantiation of the state variables of the system
  75. being monitored. A collection of particles is essentially a
  76. discretization of the posterior probability of the system.
  77. */
  78. typedef struct particle {
  79. float x; /**< current x coordinate */
  80. float y; /**< current y coordinate */
  81. float s; /**< scale */
  82. float xp; /**< previous x coordinate */
  83. float yp; /**< previous y coordinate */
  84. float sp; /**< previous scale */
  85. float x0; /**< original x coordinate */
  86. float y0; /**< original y coordinate */
  87. int width; /**< original width of region described by particle */
  88. int height; /**< original height of region described by particle */
  89. histogram* histo; /**< reference histogram describing region being tracked */
  90. double w; /**< weight */
  91. particle()
  92. {
  93. s = 1;
  94. w = 0;
  95. }
  96. } particle;
  97. histogram** ref_histos; //
  98. unsigned int num_objects;
  99. Rect*target_rect_array; //
  100. unsigned int num_particles_for_each_object;
  101. particle** particles;
  102. Hsv*hsvimg;
  103. BYTE*RGBdata;
  104. unsigned int img_height;
  105. unsigned int img_width;
  106. bool isini;
  107. int current_frame;
  108. private:
  109. void draw_point(BYTE*rgbdata, int centerX, int centerY, COLORREF color,int linewidth);
  110. void copy_partile(const particle &src, particle&dst)
  111. {
  112. dst.height = src.height;
  113. dst.histo = src.histo; //can be a problem memory leakage
  114. dst.s = src.s;
  115. dst.sp = src.sp;
  116. dst.w = src.w;
  117. dst.width = src.width;
  118. dst.x = src.x;
  119. dst.xp = src.xp;
  120. dst.x0 = src.x0;
  121. dst.y = src.y;
  122. dst.y0 = src.y0;
  123. dst.yp = src.yp;
  124. }
  125. /**************************** Function Prototypes ****************************/
  126. /**
  127. Creates an initial distribution of particles by sampling from a Gaussian
  128. window around each of a set of specified locations
  129. @param regions an array of regions describing player locations around
  130. which particles are to be sampled
  131. @param histos array of histograms describing regions in \a regions
  132. @param n the number of regions in \a regions
  133. @param p the total number of particles to be assigned
  134. @return Returns an array of \a p particles sampled from around regions in
  135. \a regions
  136. */
  137. particle**& init_distribution(Rect* regions, histogram** histos);
  138. /**
  139. Samples a transition model for a given particle
  140. @param p a particle to be transitioned
  141. @param w video frame width
  142. @param h video frame height
  143. @param rng a random number generator from which to sample
  144. @return Returns a new particle sampled based on <EM>p</EM>'s transition
  145. model
  146. */
  147. particle transition(particle p, int w, int h);
  148. /**
  149. Normalizes particle weights so they sum to 1
  150. @param particles an array of particles whose weights are to be normalized
  151. @param n the number of particles in \a particles
  152. */
  153. void normalize_weights(particle* particles, int n);
  154. /**
  155. Re-samples a set of weighted particles to produce a new set of unweighted
  156. particles
  157. @param particles an old set of weighted particles whose weights have been
  158. normalized with normalize_weights()
  159. @param n the number of particles in \a particles
  160. @return Returns a new set of unweighted particles sampled from \a particles
  161. */
  162. particle* resample(particle* particles, int n);
  163. /**
  164. Compare two particles based on weight. For use in qsort.
  165. @param p1 pointer to a particle
  166. @param p2 pointer to a particle
  167. @return Returns -1 if the \a p1 has lower weight than \a p2, 1 if \a p1
  168. has higher weight than \a p2, and 0 if their weights are equal.
  169. */
  170. static int __ cdecl particle_cmp(const void* p1,const void* p2);
  171. /**
  172. Displays a particle on an image as a rectangle around the region specified
  173. by the particle
  174. @param img the image on which to display the particle
  175. @param p the particle to be displayed
  176. @param color the color in which \a p is to be displayed
  177. */
  178. //void display_particle(IplImage* img, particle p, CvScalar color);
  179. /**
  180. Calculates the histogram bin into which an HSV entry falls
  181. @param h Hue
  182. @param s Saturation
  183. @param v Value
  184. @return Returns the bin index corresponding to the HSV color defined by
  185. \a h, \a s, and \a v.
  186. */
  187. int histo_bin(float h, float s, float v);
  188. /**
  189. Calculates a cumulative histogram as defined above for a given array
  190. of images
  191. @param imgs an array of images over which to compute a cumulative histogram;
  192. each must have been converted to HSV colorspace using bgr2hsv()
  193. @param n the number of images in imgs
  194. @return Returns an un-normalized HSV histogram for \a imgs
  195. */
  196. histogram* calc_histogram(Hsv*img, Rect rec);
  197. /**
  198. Normalizes a histogram so all bins sum to 1.0
  199. @param histo a histogram
  200. */
  201. void normalize_histogram(histogram* histo);
  202. /**
  203. Computes squared distance metric based on the Battacharyya similarity
  204. coefficient between histograms.
  205. @param h1 first histogram; should be normalized
  206. @param h2 second histogram; should be normalized
  207. @return Rerns a squared distance based on the Battacharyya similarity
  208. coefficient between \a h1 and \a h2
  209. */
  210. double histo_dist_sq(histogram* h1, histogram* h2);
  211. /**
  212. Computes the likelihood of there being a player at a given location in
  213. an image
  214. @param img image that has been converted to HSV colorspace using bgr2hsv()
  215. @param r row location of center of window around which to compute likelihood
  216. @param c col location of center of window around which to compute likelihood
  217. @param w width of region over which to compute likelihood
  218. @param h height of region over which to compute likelihood
  219. @param ref_histo reference histogram for a player; must have been
  220. normalized with normalize_histogram()
  221. @return Returns the likelihood of there being a player at location
  222. (\a r, \a c) in \a img
  223. */
  224. double likelihood(Hsv* img, int r, int c,
  225. int w, int h, histogram* ref_histo);
  226. /**
  227. Returns an image containing the likelihood of there being a player at
  228. each pixel location in an image
  229. @param img the image for which likelihood is to be computed; should have
  230. been converted to HSV colorspace using bgr2hsv()
  231. @param w width of region over which to compute likelihood
  232. @param h height of region over which to compute likelihood
  233. @param ref_histo reference histogram for a player; must have been
  234. normalized with normalize_histogram()
  235. @return Returns a single-channel, 32-bit floating point image containing
  236. the likelihood of every pixel location in \a img normalized so that the
  237. sum of likelihoods is 1.
  238. */
  239. double* likelihood_image(Hsv* img, int w, int h, histogram* ref_histo);
  240. /**
  241. Exports histogram data to a specified file. The file is formatted as
  242. follows (intended for use with gnuplot:
  243. Where n is the number of histogram bins and h_i, i = 1..n are
  244. floating point bin values
  245. @param histo histogram to be exported
  246. @param filename name of file to which histogram is to be exported
  247. @return Returns 1 on success or 0 on failure
  248. */
  249. int export_histogram(histogram* histo, char* filename);
  250. /*
  251. Computes a reference histogram for each of the object regions defined by
  252. the user
  253. @param frame video frame in which to compute histograms; should have been
  254. converted to hsv using bgr2hsv in observation.h
  255. @param regions regions of \a frame over which histograms should be computed
  256. @param n number of regions in \a regions
  257. @param export if TRUE, object region images are exported
  258. @return Returns an \a n element array of normalized histograms corresponding
  259. to regions of \a frame specified in \a regions.
  260. */
  261. histogram** compute_ref_histos(Hsv* frame, Rect* regions, int n);
  262. public:
  263. particle_filter();
  264. ~particle_filter();
  265. void getHsvformRGBimg(BYTE*rgbdata, unsigned int W, unsigned int H);
  266. void get_target(RECT*target,int n);
  267. void track();
  268. void init();
  269. void track_single_frame();
  270. };
  271. #endif


   
   
  1. #include "particle_filter.h"
  2. #include<cstdlib>
  3. #include<time.h>
  4. using namespace std;
  5. particle_filter::particle_filter()
  6. {
  7. ref_histos = NULL;
  8. time_t t;
  9. srand(time(&t));
  10. isini = true;
  11. current_frame = 0;
  12. }
  13. particle_filter::~particle_filter()
  14. {
  15. for ( int i = 0; i < num_objects; i++)
  16. {
  17. free(particles[i]);
  18. free(ref_histos[i]);
  19. }
  20. free(particles);
  21. free(ref_histos);
  22. if (hsvimg)
  23. delete[]hsvimg;
  24. if (target_rect_array)
  25. delete[]target_rect_array;
  26. }
  27. double gaussrand()
  28. {
  29. static double V1, V2, S;
  30. static int phase = 0;
  31. double X;
  32. if (phase == 0) {
  33. do {
  34. double U1 = ( double)rand() / RAND_MAX;
  35. double U2 = ( double)rand() / RAND_MAX;
  36. V1 = 2 * U1 - 1;
  37. V2 = 2 * U2 - 1;
  38. S = V1 * V1 + V2 * V2;
  39. } while (S >= 1 || S == 0);
  40. X = V1 * sqrt( -2 * log(S) / S);
  41. }
  42. else
  43. X = V2 * sqrt( -2 * log(S) / S);
  44. phase = 1 - phase;
  45. return X;
  46. }
  47. /*************************** Function Definitions ****************************/
  48. /*
  49. Creates an initial distribution of particles at specified locations
  50. @param regions an array of regions describing player locations around
  51. which particles are to be sampled
  52. @param histos array of histograms describing regions in \a regions
  53. @param n the number of regions in \a regions
  54. @param p the total number of particles to be assigned
  55. @return Returns an array of \a p particles sampled from around regions in
  56. \a regions
  57. */
  58. particle_filter::particle**&particle_filter::init_distribution(Rect* regions, histogram** histos)
  59. {
  60. //particle** particles;
  61. float x, y;
  62. int i, j, width, height;
  63. particles = (particle**) malloc( sizeof(particle*)*num_objects);
  64. for ( int i = 0; i < num_objects; i++)
  65. particles[i] = (particle*) malloc(num_particles_for_each_object* sizeof(particle));
  66. /* create particles at the centers of each of n regions */
  67. for (i = 0; i < num_objects; i++)
  68. {
  69. width = regions[i].width;
  70. height = regions[i].height;
  71. x = regions[i].leftupx + width / 2;
  72. y = regions[i].leftupy + height / 2;
  73. for (j = 0; j < num_particles_for_each_object; j++)
  74. {
  75. int xx = target_rect_array[i].leftupx + target_rect_array[i].width / 2 + target_rect_array[i].width* gaussrand();; //x;
  76. if (xx < 0)
  77. xx = 0;
  78. if (xx >= img_width)
  79. xx = img_width - 1;
  80. particles[i][j].x0 = particles[i][j].xp = particles[i][j].x = xx;
  81. int yy = target_rect_array[i].leftupy + target_rect_array[i].height / 2 +target_rect_array[i].height* gaussrand(); //y;
  82. if (yy < 0)
  83. yy = 0;
  84. if (yy >= img_height)
  85. yy = img_height - 1;
  86. particles[i][j].y0 = particles[i][j].yp = particles[i][j].y = yy;
  87. particles[i][j].sp = particles[i][j].s = 1.0;
  88. particles[i][j].width = width;
  89. particles[i][j].height = height;
  90. particles[i][j].histo = calc_histogram(hsvimg, Rect(particles[i][j].x - width / 2,
  91. particles[i][j].y - height / 2, width, height)); //histos[i];
  92. normalize_histogram(particles[i][j].histo);
  93. particles[i][j].w = 0;
  94. }
  95. }
  96. return particles;
  97. }
  98. /*
  99. Samples a transition model for a given particle
  100. @param p a particle to be transitioned
  101. @param w video frame width
  102. @param h video frame height
  103. @param rng a random number generator from which to sample
  104. @return Returns a new particle sampled based on <EM>p</EM>'s transition
  105. model
  106. */
  107. particle_filter::particle particle_filter::transition(particle p, int w, int h)
  108. {
  109. float x, y, s;
  110. particle pn;
  111. #define PI 3.1415926
  112. //double tt = 3;
  113. // sample new state using second-order autoregressive dynamics
  114. int sign = rand() % 2 == 0 ? 1 : -1;
  115. x = A1 * (p.x - p.x0) + A2 * (p.xp - p.x0) +
  116. sign* 0.05*( double(rand()) / RAND_MAX)*p.width*p.s + p.x0; //B0 * 1.0 / sqrt(2 * PI) / TRANS_X_STD*exp(-pow(double(rand()) / RAND_MAX / TRANS_X_STD, 2)) + p.x0;
  117. pn.x = MAX( 0.0, MIN(( float)w - 1.0, x));
  118. sign = rand() % 2 == 0 ? 1 : -1;
  119. y = A1 * (p.y - p.y0) + A2 * (p.yp - p.y0) +
  120. sign* 0.05*( double(rand()) / RAND_MAX)*p.height*p.s + p.y0; //B0 * 1.0 / sqrt(2 * PI) / TRANS_Y_STD*exp(-pow(double(rand()) / RAND_MAX / TRANS_Y_STD, 2)) + p.y0;
  121. pn.y = MAX( 0.0, MIN(( float)h - 1.0, y));
  122. //s = A1 * (p.s - 1.0) + A2 * (p.sp - 1.0) +
  123. // B0 * 1.0 / sqrt(2 * PI) / TRANS_S_STD*exp(-pow(double(rand()) / RAND_MAX / TRANS_S_STD, 2)) + 1.0;
  124. //pn.s = MAX(0.1, s);
  125. pn.s = 1;
  126. pn.xp = p.x;
  127. pn.yp = p.y;
  128. pn.sp = p.s;
  129. pn.x0 = p.x0;
  130. pn.y0 = p.y0;
  131. pn.width = p.width;
  132. pn.height = p.height;
  133. pn.histo = p.histo;
  134. pn.w = 0;
  135. //assert(p.width == target_rect_array[0].width);
  136. return pn;
  137. }
  138. /*
  139. Normalizes particle weights so they sum to 1
  140. @param particles an array of particles whose weights are to be normalized
  141. @param n the number of particles in \a particles
  142. */
  143. void particle_filter::normalize_weights(particle* particles, int n)
  144. {
  145. double sum = 0;
  146. int i;
  147. double maxweight = 0;
  148. for (i = 0; i < n; i++)
  149. sum += particles[i].w;
  150. for (i = 0; i < n; i++)
  151. {
  152. particles[i].w /= sum;
  153. if (particles[i].w>maxweight)
  154. maxweight = particles[i].w;
  155. }
  156. }
  157. /*
  158. Compare two particles based on weight. For use in qsort.
  159. @param p1 pointer to a particle
  160. @param p2 pointer to a particle
  161. @return Returns -1 if the \a p1 has lower weight than \a p2, 1 if \a p1
  162. has higher weight than \a p2, and 0 if their weights are equal.
  163. */
  164. int __cdecl particle_filter::particle_cmp( const void* p1, const void* p2)
  165. {
  166. particle* _p1 = (particle*)p1;
  167. particle* _p2 = (particle*)p2;
  168. if (_p1->w > _p2->w)
  169. return -1;
  170. if (_p1->w < _p2->w)
  171. return 1;
  172. return 0;
  173. }
  174. /*
  175. Re-samples a set of particles according to their weights to produce a
  176. new set of unweighted particles
  177. @param particles an old set of weighted particles whose weights have been
  178. normalized with normalize_weights()
  179. @param n the number of particles in \a particles
  180. @return Returns a new set of unweighted particles sampled from \a particles
  181. */
  182. particle_filter::particle*particle_filter::resample(particle* particles, int n)
  183. {
  184. particle* new_particles;
  185. int i, j, np, k = 0;
  186. qsort(particles, n, sizeof(particle), &particle_cmp);
  187. int nnn = 0.03*num_particles_for_each_object;
  188. int kk = 0;
  189. new_particles = (particle*) malloc( sizeof(particle)*n);
  190. int count = 0;
  191. int max_dis = (particles[ 0].height + particles[ 0].width);
  192. int cnt = 0;
  193. int maxnum = 0;
  194. for (i = 0; i < n; i++)
  195. {
  196. np = round(particles[i].w * n);
  197. //if (np <= 0)
  198. // np = 1;
  199. if (i == 0 && np < 30)
  200. np = 30;
  201. for (j = 0; j < np; j++)
  202. {
  203. //new_particles[k++] = particles[i];
  204. double dis = abs(particles[i].x - particles[ 0].x) + abs(particles[i].y - particles[ 0].y);
  205. if ( dis> max_dis/ 3)
  206. {
  207. copy_partile(particles[kk++%nnn], new_particles[k]);
  208. cnt++;
  209. }
  210. else
  211. copy_partile(particles[i], new_particles[k]);
  212. k++;
  213. if (k == n)
  214. goto exit;
  215. count++;
  216. }
  217. }
  218. for ( int i = k; i < n; i++)
  219. copy_partile(particles[kk++%nnn], new_particles[i]);
  220. ///while (k < n)
  221. // new_particles[k++] = particles[0];
  222. exit:
  223. return new_particles;
  224. }
  225. /*
  226. Displays a particle on an image as a rectangle around the region specified
  227. by the particle
  228. @param img the image on which to display the particle
  229. @param p the particle to be displayed
  230. @param color the color in which \a p is to be displayed
  231. */
  232. /*void particle_filter::display_particle(IplImage* img, particle p, CvScalar color)
  233. {
  234. int x0, y0, x1, y1;
  235. x0 = round(p.x - 0.5 * p.s * p.width);
  236. y0 = round(p.y - 0.5 * p.s * p.height);
  237. x1 = x0 + round(p.s * p.width);
  238. y1 = y0 + round(p.s * p.height);
  239. //Rectangle(img, cvPoint(x0, y0), cvPoint(x1, y1), color, 1, 8, 0);
  240. }*/
  241. /*
  242. Calculates the histogram bin into which an HSV entry falls
  243. @param h Hue
  244. @param s Saturation
  245. @param v Value
  246. @return Returns the bin index corresponding to the HSV color defined by
  247. \a h, \a s, and \a v.
  248. */
  249. int particle_filter::histo_bin( float h, float s, float v)
  250. {
  251. int hd, sd, vd;
  252. /* if S or V is less than its threshold, return a "colorless" bin */
  253. vd = MIN(( int)(v * NV / V_MAX), NV - 1);
  254. if (s < S_THRESH || v < V_THRESH)
  255. return NH * NS + vd;
  256. /* otherwise determine "colorful" bin */
  257. hd = MIN(( int)(h * NH / H_MAX), NH - 1);
  258. sd = MIN(( int)(s * NS / S_MAX), NS - 1);
  259. return sd * NH + hd;
  260. }
  261. /*
  262. Calculates a cumulative histogram as defined above for a given array
  263. of images
  264. @param img an array of images over which to compute a cumulative histogram;
  265. each must have been converted to HSV colorspace using bgr2hsv()
  266. @param n the number of images in imgs
  267. @return Returns an un-normalized HSV histogram for \a imgs
  268. */
  269. particle_filter::histogram* particle_filter::calc_histogram(Hsv*img, Rect rec)
  270. {
  271. //IplImage* img;
  272. histogram* histo;
  273. //correct window
  274. int leftup_X = rec.leftupx;
  275. int leftup_Y =rec.leftupy;
  276. if (leftup_X < 0)
  277. leftup_X = 0;
  278. if (leftup_X >= img_width - rec.width)
  279. leftup_X = img_width - rec.width - 1;
  280. if (leftup_Y < 0)
  281. leftup_Y = 0;
  282. if (leftup_Y >= img_height - rec.height)
  283. leftup_Y = img_height - rec.height - 1;
  284. Rect rect(leftup_X, leftup_Y, rec.width, rec.height);
  285. float* hist;
  286. int i, r, c, bin;
  287. int size = sizeof(histogram);
  288. histo = (histogram*) malloc( sizeof(histogram));
  289. histo->n = NH*NS + NV;
  290. hist = histo->histo;
  291. memset(hist, 0, histo->n * sizeof( float));
  292. /* extract individual HSV planes from image */
  293. /* increment appropriate histogram bin for each pixel */
  294. for (r = 0; r < rect.height; r++)
  295. for (c = 0; c < rect.width; c++)
  296. {
  297. bin = histo_bin( /*pixval32f( h, r, c )*/img[img_width*(rect.leftupy + r) + rect.leftupx + c].H,
  298. img[img_width*(rect.leftupy + r) + rect.leftupx + c].s,
  299. img[img_width*(rect.leftupy + r) + rect.leftupx + c].v);
  300. hist[bin] += 1;
  301. }
  302. return histo;
  303. }
  304. /*
  305. Normalizes a histogram so all bins sum to 1.0
  306. @param histo a histogram
  307. */
  308. void particle_filter::normalize_histogram(histogram* histo)
  309. {
  310. float* hist;
  311. float sum = 0, inv_sum;
  312. int i, n;
  313. hist = histo->histo;
  314. n = histo->n;
  315. /* compute sum of all bins and multiply each bin by the sum's inverse */
  316. for (i = 0; i < n; i++)
  317. sum += hist[i];
  318. inv_sum = 1.0 / sum;
  319. for (i = 0; i < n; i++)
  320. hist[i] *= inv_sum;
  321. }
  322. /*
  323. Computes squared distance metric based on the Battacharyya similarity
  324. coefficient between histograms.
  325. @param h1 first histogram; should be normalized
  326. @param h2 second histogram; should be normalized
  327. @return Returns a squared distance based on the Battacharyya similarity
  328. coefficient between \a h1 and \a h2
  329. */
  330. double particle_filter::histo_dist_sq(histogram* h1, histogram* h2)
  331. {
  332. float* hist1, *hist2;
  333. double sum = 0;
  334. int i, n;
  335. n = h1->n;
  336. hist1 = h1->histo;
  337. hist2 = h2->histo;
  338. /*
  339. According the the Battacharyya similarity coefficient,
  340. D = \sqrt{ 1 - \sum_1^n{ \sqrt{ h_1(i) * h_2(i) } } }
  341. */
  342. for (i = 0; i < n; i++)
  343. sum += sqrt(hist1[i] * hist2[i]);
  344. return 1.0 - sum;
  345. }
  346. /*
  347. Computes the likelihood of there being a player at a given location in
  348. an image
  349. @param img image that has been converted to HSV colorspace using bgr2hsv()
  350. @param r row location of center of window around which to compute likelihood
  351. @param c col location of center of window around which to compute likelihood
  352. @param w width of region over which to compute likelihood
  353. @param h height of region over which to compute likelihood
  354. @param ref_histo reference histogram for a player; must have been
  355. normalized with normalize_histogram()
  356. @return Returns the likelihood of there being a player at location
  357. (\a r, \a c) in \a img
  358. */
  359. double particle_filter::likelihood(Hsv* img, int r, int c,
  360. int w, int h, histogram* ref_histo)
  361. {
  362. //IplImage* tmp;
  363. histogram* histo;
  364. float d_sq;
  365. //correct window
  366. int leftup_X = c - w / 2;
  367. int leftup_Y = r - h / 2;
  368. if (leftup_X < 0)
  369. leftup_X = 0;
  370. if (leftup_X >= img_width - w)
  371. leftup_X = img_width - w - 1;
  372. if (leftup_Y < 0)
  373. leftup_Y = 0;
  374. if (leftup_Y >= img_height - h)
  375. leftup_Y = img_height - h - 1;
  376. Rect rec(leftup_X, leftup_Y, w, h);
  377. histo = calc_histogram(img, rec);
  378. normalize_histogram(histo);
  379. /* compute likelihood as e^{\lambda D^2(h, h^*)} */
  380. d_sq = histo_dist_sq(histo, ref_histo);
  381. free(histo);
  382. double re = exp(-LAMBDA * d_sq);
  383. return re;
  384. }
  385. /*
  386. Returns an image containing the likelihood of there being a player at
  387. each pixel location in an image
  388. @param img the image for which likelihood is to be computed; should have
  389. been converted to HSV colorspace using bgr2hsv()
  390. @param w width of region over which to compute likelihood
  391. @param h height of region over which to compute likelihood
  392. @param ref_histo reference histogram for a player; must have been
  393. normalized with normalize_histogram()
  394. @return Returns a single-channel, 32-bit floating point image containing
  395. the likelihood of every pixel location in \a img normalized so that the
  396. sum of likelihoods is 1.
  397. */
  398. double* particle_filter::likelihood_image(Hsv* img, int w, int h, histogram* ref_histo)
  399. {
  400. double* l, *l2;
  401. double sum = 0;
  402. int i, j;
  403. l = new double[img_height*img_width];
  404. for (i = 0; i < img_height; i++)
  405. for (j = 0; j < img_width; j++)
  406. { //setpix32f( l, i, j, likelihood( img, i, j, w, h, ref_histo ) );
  407. l[i*img_width + j] = likelihood(img, i, j, w, h, ref_histo);
  408. sum += l[i*img_width + j];
  409. }
  410. for (i = 0; i < img_height; i++)
  411. for (j = 0; j < img_width; j++)
  412. {
  413. l[i*img_width + j] /= sum;
  414. }
  415. return l;
  416. }
  417. /*
  418. Exports histogram data to a specified file. The file is formatted as
  419. follows (intended for use with gnuplot:
  420. Where n is the number of histogram bins and h_i, i = 1..n are
  421. floating point bin values
  422. @param histo histogram to be exported
  423. @param filename name of file to which histogram is to be exported
  424. @return Returns 1 on success or 0 on failure
  425. */
  426. int particle_filter::export_histogram(histogram* histo, char* filename)
  427. {
  428. int i, n;
  429. float* h;
  430. FILE* file = fopen(filename, "w");
  431. if (!file)
  432. return 0;
  433. n = histo->n;
  434. h = histo->histo;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值