KCF论文理解与源码解析
汇总博文,全面介绍KCF数学原理,测试MATLAB和C++代码实现
KCF(Kernelized Correlation Filter)基于核化的 岭回归分类器 使用循环移位得到的 循环矩阵 来采集正负样本,利用循环矩阵在 傅里叶空间 可对角化的性质,将矩阵的运算转化为元素的点乘,从而降低了运算量,使得算法满足实时性要求。同时, KCF使用 多通道HOG特征 代替单通道灰度特征,将特征扩展到多通道的非线性特征空间,达到了更高的鲁棒性和准确性。
源码及参考
- 作者源码:http://www.robots.ox.ac.uk/~joao/circulant/index.html
- GitHub源码:https://github.com/foolwood/KCF
- 2019-02-04 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:简化计算
注:最后结果的
d
i
a
g
diag
diag运算可以省略。
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的图像读取差不多,的确性能出众。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)