DSST详解

作者: 和蔼的zhxing | 来源:发表于2017-12-06 17:44 被阅读1706次

    有一段时间没有看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大小维1926,则每一个样本的特征向量维数为:19/426/4*33=744。
      窗函数:一维汉明。
      预计输出:一维高斯。

    尺寸系数

    尺寸系数

    S表示的是尺寸的级数,论文里给的是33,a是比例系数,论文中给的是1.02.
    这种尺度更新并不是线性的:


    尺寸系数

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

    伪代码

    直接上论文中的图:

    伪代码

    主要代码

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

    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

    相关文章

      网友评论

        本文标题:DSST详解

        本文链接:https://www.haomeiwen.com/subject/yducixtx.html