# 试验平台：

VS2010 + opencv2.4.10 + gsl1.8库 + RobHess粒子滤波源码

# 相关资料：

yangyangcv博主的分析及代码（建议先看）：http://www.cnblogs.com/yangyangcv/archive/2010/05/23/1742263.html

# 源码分析：

## 2、粒子的定义：

typedef struct particle {
float x;          /**< 当前x坐标 */
float y;          /**< 当前y坐标 */
float s;          /**< scale */
float xp;         /**< 之前x坐标 */
float yp;         /**< 之前y坐标 */
float sp;         /**< previous scale */
float x0;         /**< x0 */
float y0;         /**< y0 */
int width;        /**< 粒子宽度 */
int height;       /**< 粒子高度 */
histogram* histo; /**< 跟踪区域的参考直方图 */
float w;          /**< 权重 */
} particle;

### 3、特征提取：

/* 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 )*/((float*)(h->imageData + h->widthStep*r) )[c],
((float*)(s->imageData + s->widthStep*r) )[c],
((float*)(v->imageData + v->widthStep*r) )[c] );
hist[bin] += 1;
}

int histo_bin( float h, float s, float v )
{
int hd, sd, vd;

/* if S or V is less than its threshold, return a "colorless" bin */
vd = MIN( (int)(v * NV / V_MAX), NV-1 );
if( s < S_THRESH  ||  v < V_THRESH )
return NH * NS + vd;

/* otherwise determine "colorful" bin */
hd = MIN( (int)(h * NH / H_MAX), NH-1 );
sd = MIN( (int)(s * NS / S_MAX), NS-1 );
return sd * NH + hd;
}

img是目标矩形区域，h、s、v是个分量，hist就是直方图统计；NV、V_MAX....等是宏定义的固定值。
void normalize_histogram( histogram* histo )//直方图归一化
{
float* hist;
float sum = 0, inv_sum;
int i, n;

hist = histo->histo;
n = histo->n;

/* compute sum of all bins and multiply each bin by the sum's inverse */
for( i = 0; i < n; i++ )
sum += hist[i];
inv_sum = 1.0 / sum;
for( i = 0; i < n; i++ )
hist[i] *= inv_sum;
}

### 4、粒子初始化

/* 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;<span style="white-space:pre">	</span>//粒子中心
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;
}
}

## 步骤二、粒子相似度搜索、计算

### 5、粒子搜索

particle transition( particle p, int w, int h, gsl_rng* rng )//随机撒出一个粒子
{
float x, y, s;
particle pn;
//回归模型的参数即A1、A2、B0等Rob Hess在代码中已设定（我不知道是怎么来的？）
/* 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;
}

### 6、相似度计算

//计算粒子与跟踪区域直方图相似程度，越相似则权值越大
particles[j].w = likelihood( hsv_frame, cvRound(particles[j].y),
cvRound( particles[j].x ),
cvRound( particles[j].width * s ),
cvRound( particles[j].height * s ),
particles[j].histo );

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

## 步骤三、重采样

### 7、重采样

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

# over!

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客