《Fast Traking via Spatio-Temporal Context Learning》要点整理与代码实现之一

  最近读了一篇名为《Fast Tracking via Spatio-Temporal Context Learning》的论文,主要介绍了一种基于时空上下文的物体跟踪算法。在此之前,CSDN博主“zouxy09”已经写过一篇对该论文的解读http://blog.csdn.net/zouxy09/article/details/16889905。在本博文中,我没有按照原论文的思路,而是在对原文内容已经熟悉的基础上(希望读者也能在熟悉原论文后再看本博文),按照自己的思路重新归纳,主要对一些自己容易忽略的重点,或者原文中没有得到强调的逻辑关系加以整理。

 

几个概念:

贝叶斯框架(Bayesian framework):建立目标与其周围的区域在低层特征(像素强度值)上的统计相关性

时空上下文模型(Spatio-temporal context model):空间关系(量化为“空间上下文模型”(spatial context model))是目标及其邻域间固有的,时间关系则是通过加权累加每一历史帧(当前帧之前的所有帧)的空间关系而得到的

主要思想:

  基于“贝叶斯框架”建立目标物体和其局部上下文之间的时空关系,通过这一“时空模型”计算“置信图”(confidence map),由“置信图”中似然概率最大的位置预测出新的目标位置。

1.求“时空上下文模型”

  是已得到的“时空上下文模型”(Spatio-temporal context model)(其中加权累加了第t-1帧到第1帧的所有“空间上下文模型”),可用于计算本帧的“置信图”,从而得到本帧的目标位置。是在当前帧(第t帧)中新计算出来的“空间上下文模型”(spatial context model)。是由以上两个模型按权相加后得到的新“时空上下文模型”,用于在下一帧中计算其“置信图”,得到下一帧的新目标位置。是权值,是一个常数。

(1)“时空上下文模型”的初始化

  对第1帧,上式显然不成立,因为我们并没有第0帧的“空间上下文模型”和“时空上下文模型”,所以在初始化时,直接令第1帧的“时空上下文模型”直接等于其“空间上下文模型”。

2.求“置信图”

  置信图由上式求出,有这么几点应该注意:

  • 当前帧是第t+1帧,用该式求“置信图”的目的是为了求出本帧的目标位置;
  • 此时此刻手头上拥有的信息是:在上一帧中更新了的“时空上下文模型”,当前帧(第t+1帧)的像素强度值上一帧的目标位置和目标尺度
  • 用FFT加速卷积运算
  • 由于该置信图的值在每一帧中都会被更新,是不断变化的,且与时空信息有关,是从全局角度来看的,所以我将其称为“绝对置信图”,那么对应的还有“相对置信图”,在后面我会说到。在这里只需要记住,“绝对置信图”在每一次迭代中都要重新计算,是不断更新的;而“相对置信图”是不变的,是一个常值。 
  • 第一帧不用求该置信图,因为“绝对置信图”总是用上一帧的目标位置和尺度来求的,而在第一帧中,我们并没有第0帧的目标位置和尺度,我们初始化的直接是第1帧的目标位置和尺度,况且我们已经由初始化得到了第1帧的目标位置和尺度,也就不用由“绝对置信图”来求该帧的目标位置和尺度了。

3.求“空间上下文模型”

  若已知本帧的目标位置,则在以该目标位置为中心的邻域(局部上下文)内,“置信图”可以如下建模:

这里,和b都是常数,故其值只与目标邻域中各点相对目标位置的距离有关,因此当该邻域大小确定时,该“置信图”是一个常量矩阵,不因每一帧目标位置的变化而变化,因此我将该置信图称为“相对置信图”,意指其大小只与目标周围点到目标的相对距离有关。

  以上两式用来求“空间上下文模型”,但请注意它们均没有脚标,即没有时间上下文的概念。这也就是说,所有计算利用的都是本帧自身的信息(本帧自己的目标位置、本帧自己的目标尺度、本帧自己的像素强度值等)。因此在计算“空间上下文模型”时,特别要注意,我们首先要得到本帧的目标位置和目标尺度。因此除了第1帧外,context prior model要求两次,一次用上一帧的目标位置和尺度来求(用于求本帧的目标位置),一次用本帧的目标位置和尺度来求(用于求本帧的空间上下文模型)。

 

算法流程:

 

 

代码实现(Matlab):

  在参考了作者的matlab代码后,我按照自己画的流程图重新写了一遍,参数初始化则完全照搬了作者的。

% My implementation for STC model based tracking
%%
clear, clc, close all;
%%
fftw('planner','patient');
%%
addpath('./data');
img_dir = dir('./data/*.jpg');
%% Initializaiton
% constant parameter
target_sz = [95, 75];   % (rows, cols)
context_sz = target_sz * 2;    % (rows, cols)
rho = 0.075;
alpha = 2.25;
beta = 1;
lambda = 0.25;
num = 5;
hamming_window = hamming(context_sz(1)) * hann(context_sz(2))';
% variable initialization
target_center = [65, 161] + target_sz ./ 2;  % (row, col)
sigma = mean(target_sz);
scale = 1;
[rs, cs] = ndgrid((1:context_sz(1)) - context_sz(1)/2, (1:context_sz(2)) - context_sz(2)/2);
dist = rs.^2 + cs.^2; % a 190x150 matrix
conf = exp( -1 .* (sqrt(dist) ./ alpha).^beta );
conf = conf/sum(sum(conf)); % normalization
conff = fft2(conf);
scale_arr = zeros(num+1, 1);
%% 
for frame = 1:numel(img_dir)
    % read one frame
    img = imread(img_dir(frame).name);
    im = rgb2gray(img);
    % compute the context prior model with the target center and sigma of the previous frame
    window = hamming_window .* exp(-0.5 * dist / (sigma^2));  % It should be a 190x150 matrix
    window = window/sum(sum(window));%normalization
    context_prior = compute_prior(im, target_center, context_sz, window);   % using the target_center and sigma of the previous frame
    if frame > 1
        % compute the confidence map
        conf_map = real(ifft2( Hstcf .* fft2(context_prior) ));
        % find the new target center of the current frame
        [row, col] = find(conf_map == max(conf_map(:)), 1);
        target_center = target_center - context_sz / 2 + [row, col];    % here is weird, why we should substract 'context_sz/2' from the 'target_center'?
        % update sigma to current frame
        sigma = sigma * scale;
        % compute the new context prior model with the target center and sigma
        % of the current frame
        window = hamming_window .* exp(-0.5 * dist / (sigma^2));  % It should be a 190x150 matrix
        window = window/sum(sum(window));%normalization
        context_prior = compute_prior(im, target_center, context_sz, window);   % using the new target_center and sigma of current frame
        % update the confidence map of the current frame
        conf_map = real(ifft2( Hstcf .* fft2(context_prior) ));
        % update scale (you can also keep 'scale=1')
%         scale_arr(1:num) = scale_arr(2:end);
%         scale_arr(num) = max(conf_map(:));
%         scale_avr = 0;
%         if frame > (num + 1)
%             for i = 1:num
%                 scale_avr = scale_avr + sqrt(scale_arr(num + 2 - i) / scale_arr(num + 1 - i));
%             end
%             scale = (1 - lambda) * scale + lambda * scale_avr / num;
%         end
    end
    % learn the spatial context model
    hscf = conff ./ fft2(context_prior);
    % update spatio_temporal context model
    if frame == 1
        Hstcf = hscf;
    else
        Hstcf = (1-rho) * Hstcf + rho * hscf;
    end
    %visualization
    target_sz([2,1]) = target_sz([2,1])*scale;% update object size
    rect_position = [target_center([2,1]) - (target_sz([2,1])/2), (target_sz([2,1]))];  
    imagesc(uint8(img))
    colormap(gray)
    rectangle('Position',rect_position,'LineWidth',4,'EdgeColor','r');
    hold on;
    text(5, 18, strcat('#',num2str(frame)), 'Color','y', 'FontWeight','bold', 'FontSize',20);
    set(gca,'position',[0 0 1 1]); 
    pause(0.001); 
    hold off;
    drawnow;
end
%% The end

  代码目前还存在一些问题有待讨论:

  • 自己写的尺度更新的部分不能工作,因此我把他注释掉了,现在只能工作于单尺度(scale=1);
  • conf_map = real(ifft2( Hstcf .* fft2(context_prior) )) 这句中,ifft2的结果仍是复数,因此作者取了其实部用于后续计算,为什么ifft2的结果是复数?为什么作者只取其实部而不是取其模?
  • “hamming window”对结果的影响有多大;对原图的像素强度值作者也做了normalization,如果把这些都去掉,对结果影响有多大,这还有待测试
  • 目标位置初始化:target_center = [65, 161] + target_sz ./ 2;目标位置更新:target_center = target_center - context_sz / 2 + [row, col],加上target_sz/2和减去context_sz/2显然是作者有意而为之的,意义何在?
posted @ 2014-04-23 11:57  午后阳光*  阅读(3740)  评论(1编辑  收藏  举报