前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DSST详解

DSST详解

作者头像
和蔼的zhxing
发布2018-09-04 13:11:34
1.4K0
发布2018-09-04 13:11:34
举报

有一段时间没有看tracking了,前面一个月老师没有找,我也没有看文章,主要去看c++和cs231n去了。上周一老师找了我一次,于是赶紧把tracking又拾起来,把老师给的视频在前面的代码上跑了下,这周又看了篇新论文。

最开始的应该是MOOSE,作者没有给源码,所以论文理解得并不是很透彻,CSK以及KCF/DCF都是仔细研究了源码的,自认为还算比较了解了,接下来的CN,其实了解了KCF/DCF就很简单了,无非是另一种多特征的融合,融合方式都差不多。

昨天开始看DSST,只看了前面的部分,后边的实验没有怎么看,又去看了下matlab的源码,代码结构很清晰,因为框架还是CSK得大框架,结合作者的注释很快就看完了,做个整理。

MOOSE paper

是跟踪领域相关滤波的第一篇文章,开创性意义。

CSK paper

利用循环矩阵解决了训练量的问题,不用在进行随机仿射来得到样本。这个是单通道的, 作者只使用了灰度信息。

KCF/DCF paper

和CSK是同一个作者,和CSK的改进很小,主要贡献和CSK相比在于提供了一种把多通道特征融合进相关滤波框架的方法。

CN paper

和KCF/DCF是同一时期的,不同的是用了颜色通道,论文里作者比较了各种颜色空间的表现。

DSST paper

DSST解决了另外一个关键问题,那就是尺度更新。

这5篇文章是相关滤波的基础,今天这里主要写一下DSST的论文思路。

MOOSE基础

DSST是在MOOSE的基础上来的,所以很有必要再回顾一下MOOSE,正好昨天看论文的时候把MOOSE里的公式的推到再看了看了一遍。

信号处理里面有相关的概念,用来描述两个信号之间的联系,有自相关和互相关之分。

假设有两个信号f和g,则两个信号的相关(correlation)定义为:

这里分别给出的是连续信号和离散信号的公式,看起来和卷积很像。星号表示复共轭。

correlation的直观解释就是表示的是两个信号在某个时刻的相似程度,相关滤波应用到跟踪领域最简单的解释就是:两个信号越相似,其相关值就越高,跟踪的时候就是要找到响应最大的位置。

作者提出的滤波器叫做Minimum Output Sum of Squared Error(MOSSE)。

按照上面说的思路,我们需要找到一个滤波器,使其在目标上的响应最大:

其中g是输出,f是输入,h是滤波器,输出我们给成一个高斯分布,在目标点的值最大。

这是一个卷积计算,真的要这么直接算的话计算量还是很大的,所以很容易想到,变换到频域进行点乘:

注意这里和卷积稍有不同,简单的来说,卷积操作的时候卷积核要反转,相关不用,其他操作是一样的,变换到频域里卷积操作是频域点乘,而相关要给卷积核的频域加上共轭。

为方便写成下面这样:

简单变换:

实际使用中用一张图像直接这样算肯定是太粗暴了,为了提高滤波器的鲁棒性,我们同事考虑目标的m个图像作为参考,于是提出了下面这个模型:

上面的操作都是element-wise的,因为要想整体最小,使得每个元素的MOOSE最小就好:

那么我们求导,令导数为0:

推导如下:

和实数求导不太一样,但其实不难,注意共轭乘法的一些等价,就可以化简出来了。

上面得到的是每个元素的,综合起来:

作者的文章中对于跟踪框进行了随机仿射变换(因为没有看源码我也不知道作者是怎样仿射变换的)获取了一系列的训练样本f,而g则是由高斯函数产生,就可以计算滤波器了。

为了让滤波器对形变,光照等外界条件具有更好的鲁棒性,采取了如下的更新策略(这种更新策略在CN,DSST中都有使用):

把滤波器的模型分为分子分母两部分分别进行更新。

得到滤波器再计算响应就相对简单了:

z是输入的特征图, lambda是为了防止分母为0。

DSST思想

1.1维滤波器用于评估目标尺度的变化,2维滤波器用于评估目标位置的变化,3维滤波器用于详尽的尺度空间中的目标定位。

2.实际代码中作者用了两个相关滤波器,且是相互独立的,位置滤波器(translation filter)和尺度滤波器(scale filter),分别对目标定位和尺度评估,而且两个滤波器应用的原理和方式也是相同的。

3.两个滤波器是相互独立的,所以可以选用不同的特征来计算。

  • 位置滤波器(2维) 特征:28维,27维fhog加上一维的灰度。 窗函数:二维汉明。 预计输出:二维高斯。 这里的位置滤波器和CN里的更新方式是一样的。
  • 尺寸滤波器(1维) 特征:用的fhog特征,取31维(27+4)。 这个稍微难一点:首先以目标位中心提取33中不同尺度下的样本,然后把所有样本resize到固定的尺寸,在这个固定的尺寸下提取fhog特征,每个样本的特征串成一个特征向量(和KCF中不同), 大小和resize的大小有关。 比如:resize大小维19_26,则每一个样本的特征向量维数为:19/4_26/4*33=744。 窗函数:一维汉明。 预计输出:一维高斯。

尺寸系数

尺寸系数

S表示的是尺寸的级数,论文里给的是33,a是比例系数,论文中给的是1.02.

这种尺度更新并不是线性的:

尺寸系数

可以看出,尺寸越小的话斜率是越小的,也就是说,在小尺度的搜索精度比大尺度要高。

伪代码

直接上论文中的图:

伪代码

主要代码

主要代码在dsst.m里,我写了比较详细的注释,放在下面可以帮助理解。

代码语言:javascript
复制
for frame = 1:num_frames,
    %load image
    im = imread([video_path img_files{frame}]);

    tic;
    
    if frame > 1
        
        % extract the test sample feature map for the translation filter
        xt = get_translation_sample(im, pos, sz, currentScaleFactor, cos_window);
        
        % calculate the correlation response of the translation filter
        xtf = fft2(xt);      %依然是28维
        response = real(ifft2(sum(hf_num .* xtf, 3) ./ (hf_den + lambda)));   %这里是乘起来,然后再复频域想加,完了之后再做ifft取实部
        
        % find the maximum translation response          %相应的最大点
        [row, col] = find(response == max(response(:)), 1);
        
        % update the position           %根据这个最大点然后再去确定尺寸
        pos = pos + round((-sz/2 + [row, col]) * currentScaleFactor);
        
        % extract the test sample feature map for the scale filter
        % 获得scale feature  
        xs = get_scale_sample(im, pos, base_target_sz, currentScaleFactor * scaleFactors, scale_window, scale_model_sz);
        
        % calculate the correlation response of the scale filter
        xsf = fft(xs,[],2);  
        scale_response = real(ifft(sum(sf_num .* xsf, 1) ./ (sf_den + lambda)));   %求最大响应因子,这里的样本稍多一点,因为Fhog提取的比较多,一个尺度提取了几百个特征
        
        % find the maximum scale response
        recovered_scale = find(scale_response == max(scale_response(:)), 1);        %对应的尺寸索引
        
        % update the scale
        currentScaleFactor = currentScaleFactor * scaleFactors(recovered_scale);     %更新尺寸
        if currentScaleFactor < min_scale_factor                                     %处理极值
            currentScaleFactor = min_scale_factor;
        elseif currentScaleFactor > max_scale_factor
            currentScaleFactor = max_scale_factor;
        end
    end
    
    % extract the training sample feature map for the translation filter
    % 这里得到的是特征图,27维fhog和1维的灰度,都是加了窗之后的。  共28维特征
    xl = get_translation_sample(im, pos, sz, currentScaleFactor, cos_window);
    
    % calculate the translation filter update  预测的滤波器更新,这
    xlf = fft2(xl);
    new_hf_num = bsxfun(@times, yf, conj(xlf));      %分子,还是28维的复数
    new_hf_den = sum(xlf .* conj(xlf), 3);          %分母,这里把每一维对应位置加起来了,因为自相关得到的是实数可以直接加
    
    % extract the training sample feature map for the scale filter
    %这里得到的是scale用的特征,33个尺度都得到特征,
    %每个尺度计算fhog之前都会resize到一个固定尺寸,这里是19*26,那么得到的Fhog特征是19/4*26/4*31=744维的特征,串联起来当做一列
    xs = get_scale_sample(im, pos, base_target_sz, currentScaleFactor * scaleFactors, scale_window, scale_model_sz);
    
    % calculate the scale filter update
    xsf = fft(xs,[],2);          %没一行做fft
    new_sf_num = bsxfun(@times, ysf, conj(xsf));   %算互相关
    new_sf_den = sum(xsf .* conj(xsf), 1);     %自相关,然后每一列都加起来,是1*33维的一个向量
    
    
    if frame == 1       %初始化
        % first frame, train with a single image
        hf_den = new_hf_den;
        hf_num = new_hf_num;
        
        sf_den = new_sf_den;
        sf_num = new_sf_num;
    else
        % subsequent frames, update the model,更新模型
        hf_den = (1 - learning_rate) * hf_den + learning_rate * new_hf_den;
        hf_num = (1 - learning_rate) * hf_num + learning_rate * new_hf_num;
        sf_den = (1 - learning_rate) * sf_den + learning_rate * new_sf_den;
        sf_num = (1 - learning_rate) * sf_num + learning_rate * new_sf_num;
    end
    
    % calculate the new target size
    target_sz = floor(base_target_sz * currentScaleFactor);
    
    %save position
    positions(frame,:) = [pos target_sz];
    
    time = time + toc;
    
    
    %visualization   %可视化
    if visualization == 1
        rect_position = [pos([2,1]) - target_sz([2,1])/2, target_sz([2,1])];
        if frame == 1,  %first frame, create GUI
            figure('Name',['Tracker - ' video_path]);
            im_handle = imshow(uint8(im), 'Border','tight', 'InitialMag', 100 + 100 * (length(im) < 500));
            rect_handle = rectangle('Position',rect_position, 'EdgeColor','g');
            text_handle = text(10, 10, int2str(frame));
            set(text_handle, 'color', [0 1 1]);
        else
            try  %subsequent frames, update GUI
                set(im_handle, 'CData', im)
                set(rect_handle, 'Position', rect_position)
                set(text_handle, 'string', int2str(frame));
            catch
                return
            end
        end
        
        drawnow
%         pause
    end
end

FHOG

其实fhog这块还是挺复杂的,当时看KCF的时候就卡了很久,也做了整理,详见这里

code

还有我加了注释的代码:code

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.12.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MOOSE基础
  • DSST思想
  • 尺寸系数
  • 伪代码
  • 主要代码
  • FHOG
  • code
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档