KCF(Kernelized Correlation Filter)基於核化的 嶺迴歸分類器 使用循環移位得到的 循環矩陣 來採集正負樣本,利用循環矩陣在 傅里葉空間 可對角化的性質,將矩陣的運算轉化爲元素的點乘,從而降低了運算量,使得算法滿足實時性要求。同時, KCF使用 多通道HOG特徵 代替單通道灰度特徵,將特徵擴展到多通道的非線性特徵空間,達到了更高的魯棒性和準確性。
源碼及參考
- 作者源碼:http://www.robots.ox.ac.uk/~joao/circulant/index.html
- GitHub源碼:https://github.com/foolwood/KCF
- 2019-01-03 KCF跟蹤算法原理 入門詳解
- 2018-10-23 KCF論文詳解與復現
- 2016-12-08 KCF入門詳解
- 2016-09-30 KCF目標跟蹤方法分析與總結
- 2016-03-24 KCF高速跟蹤詳解與公式推導
- 2017-05-07 KCF公式推導錯誤及驗證
- 數據集 OTB評估指標
- 其他 KCF代碼在OTB2015數據集上的坑
數據集
論文中提及所用的數據集是 OTB2013 Y. Wu, J. Lim, and M. H. Yang, “Online object tracking: A benchmark,” in CVPR, 2013
共包含50個視頻序列。官方下載:Visual Tracker Benchmark
視頻列表:
videos = {'basketball', 'bolt', 'boy', 'car4', 'carDark', 'carScale', ...
'coke', 'couple', 'crossing', 'david2', 'david3', 'david', 'deer', ...
'dog1', 'doll', 'dudek', 'faceocc1', 'faceocc2', 'fish', 'fleetface', ...
'football', 'football1', 'freeman1', 'freeman3', 'freeman4', 'girl', ...
'ironman', 'jogging', 'jumping', 'lemming', 'liquor', 'matrix', ...
'mhyang', 'motorRolling', 'mountainBike', 'shaking', 'singer1', ...
'singer2', 'skating1', 'skiing', 'soccer', 'subway', 'suv', 'sylvester', ...
'tiger1', 'tiger2', 'trellis', 'walking', 'walking2', 'woman'};
MATLAB 代碼測試
Quickstart:
- Extract code somewhere.
- The tracker is prepared to run on any of the 50 videos of the Visual Tracking Benchmark [3]. For that, it must know where they are/will be located. You can change the default location ‘base_path’ in ‘download_videos.m’ and
run_tracker.m
.- If you don’t have the videos already, run
download_videos.m
(may take some time).- Execute ‘run_tracker’ without parameters to choose a video and test the KCF on it.
注意:
- 在國內用腳本下載數據集容易失敗,建議前往官網手動下載;
- 代碼不兼容部分需要按提示更改,如show_video.m中第24行的
Number
應改爲NumberTitle
等,MATLAB2018環境可直接下載調整好的代碼:MATLAB 2018 KCF源碼
測試環境:
測試結果:
>> run_tracker all gaussian hog %Kernelized Correlation Filter (KCF)
從最後結果來看,KCF(0.742,293
)要優於論文結果(0.732,172), DCF(0.730, 604
)也優於論文結果(0.728, 292). 代碼相同的前提下,可能是硬件不同以及MATLAB版本升級帶來了巨大的性能提升。
MATLAB 代碼分析
只對
KCF-HOG
部分的代碼進行分析
性能評估接口:
run_tracker.m
這是並行測試50個視頻序列,最後對結果取平均。從下面的跟蹤接口代碼來看,img_files
中存放圖片名稱,在tracker
函數中進行讀取並跟蹤。從tic()
toc()
包括的代碼來看,只測量跟蹤算法消耗的時間,imread()
時間不計入。
跟蹤接口代碼:
run_tracker.m
跟蹤參數:
padding = 1.5; // extra area surrounding the target
feature_type = 'hog'; // feature type
kernel.type = 'gaussian'; // kernel
kernel.sigma = 0.5; // gaussian kernel bandwidth
lambda = 1e-4; // regularization
output_sigma_factor = 0.1; // spatial bandwidth (proportional to target)
interp_factor = 0.02; // linear interpolation factor for adaptation of model parameters
cell_size = 4; // HOG cell size
features.hog = true; // enable HOG feature
features.hog_orientations = 9; // the number of HOG bins
跟蹤代碼:
與論文中的僞代碼相差不大:
這是由以下的核心公式得出的。
KCF核心公式
-
核相關矩陣的初始向量:
-
核化後的嶺迴歸分類器權值:
-
快速檢測:
KCF公式推導
Step 1:KCF的基本模型是嶺迴歸分類器
Step 2:爲了 簡化閉式解的計算,消除矩陣乘法與求逆運算,以及爲了 增廣樣本,需要引入循環矩陣。
循環矩陣有着良好性質:
離散傅里葉變換簡介:
Step 3:簡化計算
注:最後結果的 運算可以省略。
Step 4:爲了提高分類器的準確度,解決“線性不可分”問題,對嶺迴歸分類器進行 “核化”。
核空間的嶺迴歸:
Step 5:核化分類器的簡化計算
對閉式解進行同等化簡(對角化、傅里葉變換):
Step 6:核相關矩陣的加速計算
Step 7:快速檢測
Step 8:選用多通道HOG特徵提升準確率。對於多通道的特徵描述符,只需在傅立葉域中對對每個通道的各個點積求和即可。
HOG特徵與FHOG特徵:
C++ 代碼測試
需要修改數據集,這裏只對Coke序列進行了測試。OpenCV版本 4.x,修改後的可運行代碼和數據集已經上傳: Streamlined KCF.zip
video info:
- img size (640, 480)
- roi size (48, 80)
- win size (120, 200) = roi * 2.5
- frame count 291
相比MATLAB的測試結果(143 fps),慢了太多。根據作者GitHub所描述的,這並不是單一尺度的跟蹤,使用的特徵是FHOG+CN,因此測試基本性能需要將這些參數清零:
再次測試,速度明顯提升:
此時,C++ 版本的算法實現參數爲:單一尺度、僅使用灰度圖像的FHOG特徵、使用Gaussian核,達到平均幀率 110 fps;跟蹤效果方面僅可以抵抗小部分遮擋,完全遮擋則會出現目標丟失。
OpenCV 代碼測試
版本 4.1.2
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/tracking.hpp>
using namespace std;
int main(int argc, char* argv[])
{
// 讀取視頻序列
string frame_files = "../datasets/OTB2013/Coke/img/%04d.jpg";
cv::VideoCapture cap(frame_files);
int frame_height = int(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
int frame_width = int(cap.get(cv::CAP_PROP_FRAME_WIDTH));
int frame_count = (int)cap.get(cv::CAP_PROP_FRAME_COUNT);
printf("video info: (%d, %d), %d frames\n", frame_width, frame_height, frame_count);
cv::Mat frame;
cap >> frame;
cv::Rect2d bbox(298, 160, 48, 80);
// 跟蹤測試
cv::Ptr<cv::Tracker> tracker;
cv::TrackerKCF::Params tracker_params;
tracker_params.detect_thresh = 0.3f;
tracker = cv::TrackerKCF::create(tracker_params);
tracker->init(frame, bbox);
double total_time_s = 0.;
for (int i = 0; i < frame_count - 1; ++i)
{
cap >> frame;
double time_profile_counter = cv::getTickCount();
tracker->update(frame, bbox);
time_profile_counter = cv::getTickCount() - time_profile_counter;
auto time = time_profile_counter / cv::getTickFrequency();
total_time_s += time;
std::cout << " -> speed : " << 1. / time << " fps" << std::endl;
}
cap.release();
std::cout << "\nAverage speed " << (frame_count - 1) / total_time_s << " fps" << std::endl;
std::cout << "\nProcessing time: " << total_time_s << " s." << std::endl;
return 0;
}
同樣的數據集,比着上一節的Streamlined KCF
要快的多,並且高於MATLAB(143 fps) 的測試結果。此時採用的是 cv::TrackerKCF 默認參數,選擇的是壓縮後的ColorName特徵,並不是論文中設計的FHOG特徵。從跟蹤效果上看,無法應對小部分遮擋,在 OTB2013/Coke 數據集中 第10幀往後即丟失目標。
關於幀率統計需要說明的是:
- 評價tracker的性能,應該只統計跟蹤時間,圖像讀取時間是被排除的,在作者的MATLAB源碼中也是這麼計時的(上文中有提及)。
- 如果在
for/while
循環外進行計時,則連帶統計了imread的耗時,結果有所不同:總耗時 2.498 s,由此可見,KCF的跟蹤性能與OpenCV的圖像讀取差不多,的確性能出衆。