1. 程式人生 > >【技術向】目標跟蹤DSST改進版fDSST演算法程式碼分析

【技術向】目標跟蹤DSST改進版fDSST演算法程式碼分析

MD大神的fDSST是DSST的加速改進版,文章發表在TPAMI17上先給文章地址:

http://www.cvl.isy.liu.se/en/research/objrec/visualtracking/scalvistrack/DSST_TPAMI.pdf

fDSST程式碼matlab在作者主頁有提供:http://www.cvl.isy.liu.se/en/research/objrec/visualtracking/scalvistrack/index.html

fDSST的加速主要體現在PCA將尺度特徵維度縮減 。

程式碼分析:

run_tracker.m部分程式碼沒有區別主要完成了視訊資料載入初始化引數等,fDSST.m程式碼中體現了與DSST的區別。

 下面是初始化的尺度部分,主要建立了17個尺度變化因子和33個內插尺度變化因子,並且建立了尺度迴歸目標ys和尺度cos窗,其它則是一些細節的考慮

可以看到這些與二維影象的初始化沒有本質的差別,就是換成一維的操作,將二維影象向量化則變成了一維。

if nScales > 0
    scale_sigma = nScalesInterp * scale_sigma_factor;
    
    scale_exp = (-floor((nScales-1)/2):ceil((nScales-1)/2)) * nScalesInterp/nScales;
    scale_exp_shift = circshift(scale_exp, [0 -floor((nScales-1)/2)]);
    
    interp_scale_exp = -floor((nScalesInterp-1)/2):ceil((nScalesInterp-1)/2);
    interp_scale_exp_shift = circshift(interp_scale_exp, [0 -floor((nScalesInterp-1)/2)]);
    
    scaleSizeFactors = scale_step .^ scale_exp;
    interpScaleFactors = scale_step .^ interp_scale_exp_shift;
    
    ys = exp(-0.5 * (scale_exp_shift.^2) /scale_sigma^2);
    ysf = single(fft(ys));
    scale_window = single(hann(size(ysf,2)))';
    
    %make sure the scale model is not to large, to save computation time
    if scale_model_factor^2 * prod(init_target_sz) > scale_model_max_area
        scale_model_factor = sqrt(scale_model_max_area/prod(init_target_sz));
    end
    
    %set the scale model size
    scale_model_sz = floor(init_target_sz * scale_model_factor);
    
    im = imread(s_frames{1});
    
    %force reasonable scale changes
    min_scale_factor = scale_step ^ ceil(log(max(5 ./ sz)) / log(scale_step));
    max_scale_factor = scale_step ^ floor(log(min([size(im,1) size(im,2)] ./ base_target_sz)) / log(scale_step));
    
    max_scale_dim = strcmp(params.s_num_compressed_dim,'MAX');
    if max_scale_dim
        s_num_compressed_dim = length(scaleSizeFactors);
    else
        s_num_compressed_dim = params.s_num_compressed_dim;
    end
end


在後面的迴圈中主要思路就是提取特徵,訓練得到模型引數,提取下一幀影象patch的特徵,利用訓練好的模型計算響應,得到下一幀的位置和尺度,如此迴圈;

尺度的計算可以認為與位置的計算是分開的,尺度資訊就是一個值:當前幀尺度因子,乘上固定的初始size則是當前幀的size;

我們先看尺度訓練程式碼部分,在後半部

if nScales > 0
        
        %create a new feature projection matrix
        [xs_pca, xs_npca] = get_scale_subwindow(im, pos, base_target_sz, currentScaleFactor*scaleSizeFactors, scale_model_sz);
        %上面一句提取了17個不同尺度的patch再統一resize到scale_model_sz大小,然後再分別提取這些patch的hog特徵,將hog特徵拉成一維的
        %最後輸出的xs_pca是17個一維的hog向量,用於後面的降維,後面的那個變數沒用,是空的
        if frame == 1
            s_num = xs_pca;
        else
            s_num = (1 - interp_factor) * s_num + interp_factor * xs_pca;
        end;
        %上面兩句用於特徵的更新,目的使模型對於跟蹤目標的魯棒性變強
        bigY = s_num;
        bigY_den = xs_pca;
        
        if max_scale_dim
            [scale_basis, ~] = qr(bigY, 0);
            [scale_basis_den, ~] = qr(bigY_den, 0);
        else
            [U,~,~] = svd(bigY,'econ');
            scale_basis = U(:,1:s_num_compressed_dim);
        end
        scale_basis = scale_basis';
        %上面使用奇異值分解得到pca變換矩陣,原始碼中將維度最大化壓縮從744維到17維
        %create the filter update coefficients
        sf_proj = fft(feature_projection_scale([],s_num,scale_basis,scale_window),[],2);
        sf_num = bsxfun(@times,ysf,conj(sf_proj));
        %通過降維得到的模型矩陣只有17*17大小,獲得了極大加速
        xs = feature_projection_scale(xs_npca,xs_pca,scale_basis_den',scale_window);
        xsf = fft(xs,[],2);
        new_sf_den = sum(xsf .* conj(xsf),1);
        
        if frame == 1
            sf_den = new_sf_den;
        else
            sf_den = (1 - interp_factor) * sf_den + interp_factor * new_sf_den;
        end;
        %更新模型,和特徵更新的原因相同
    end

再來看看檢測部分的尺度程式碼

if nScales > 0
            
            %create a new feature projection matrix
            [xs_pca, xs_npca] = get_scale_subwindow(im,pos,base_target_sz,currentScaleFactor*scaleSizeFactors,scale_model_sz);
            
            xs = feature_projection_scale(xs_npca,xs_pca,scale_basis,scale_window);
            xsf = fft(xs,[],2);
            %提取待檢測patch的不同尺度的特徵並且降維,pca矩陣用的也是訓練部分的那個矩陣
            scale_responsef = sum(sf_num .* xsf, 1) ./ (sf_den + lambda);
            %計算響應,這是個17維的向量
            interp_scale_response = ifft( resizeDFT(scale_responsef, nScalesInterp), 'symmetric');
            %內插分出了33維的相應的向量
            recovered_scale_index = find(interp_scale_response == max(interp_scale_response(:)), 1);
            %找到響應值最大的所對應的那個尺度因子
            %set the scale
            currentScaleFactor = currentScaleFactor * interpScaleFactors(recovered_scale_index);
            %adjust to make sure we are not to large or to small
            if currentScaleFactor < min_scale_factor
                currentScaleFactor = min_scale_factor;
            elseif currentScaleFactor > max_scale_factor
                currentScaleFactor = max_scale_factor;
            end
            %對尺度因子做合理性判斷
 end

綜上得到了尺度因子,注意得到的位置偏移也要乘上這個因子

最後得到了當前幀的最佳size

target_sz = floor(base_target_sz * currentScaleFactor);

在我的機器上跑個dog的demo達到了55fps,i5的電腦,還是很快的,歡迎各位與我討論~