计算机视觉CV 之 CMT跟踪算法分析一

1 简介

这个算法的全称是Clustering of Static-Adaptive Correspondences for Deformable Object Tracking,文章发表在CVPR2015上,官方的网址为:

这个作者就是OpenTLD的C++版本的作者,包括ROS版的OpenTLD也是基于他的代码改的。 对于CMT这个跟踪算法,我在iPhone5s上做了实际测试,跟踪效果超乎想象,在我比较了TLD,CT,Color Tracking,Struck等等顶级算法的效果之后得到了这样的结论。这个算法是可以实用的跟踪算法,虽然它也有缺点,之后我会说。实时性和跟踪效果都一流。

本文主要目的是分析这个跟踪算法。

2 基本原理

对于物体的视觉跟踪,基本的思路就是能够不断监测到物体的特征,从而不断的得到物体的位置,实现跟踪。常见的有三种方法:

第1是基于整体的模型来跟踪,比如说TLD,通过不断的更新模型(也就是学习的过程)来实现对物体特征的良好表示。第2是基于物体的局部来跟踪,就是将物体分解为多个部分,对每一部分进行单独的跟踪,采用光流等方法第3是基于物体的特征点来跟踪,就是实时的监测物体的特征点,与一开始的特征点进行匹配的方法来实现物体的跟踪。

从上面的方法看现在的跟踪算法确实不能简单的用跟踪两个字来描述,里面的算法其实使用了物体检测,识别,机器学习等各种各样的方法。只要能框住视频中的一个物体,然后不断跟着,那么这个算法就是跟踪算法,跟踪算法的好坏也完全取决于能不能很好的框住。实际上,现在很多跟踪算法就是检测的算法。

那么CMT算法采用的是第三种思路,就是利用特征点。为什么?第一个理由恐怕是快!如果以神经网络来获取特征,那么那么多的参数,算到什么时候?不知道。而采用特征点的话,我们知道OpenCV中集成了很多检测特征点的算法,比如SIFT,FAST,BRISK等等,有的比如FAST速度很快的。而且这么做连滑动窗口检测都可以省掉啦。

那么问题在于如何判断下一帧的图像中哪些特征点是与当前的框中的特征点相匹配的问题了?只要能够很好地找到下一帧中物体的特征点,跟踪也就完成了。

因此,为了解决这个问题,作者做了一个看起来很简单的创新:就是计算特征点的相对位置,以框的中心来进行计算,对于不形变的物体而言,不管物体怎么移动旋转,其上面的特征点相对中心的距离是在缩放比例下是确定的,因此可以由此来排除不是的特征点。

作者获取下一帧的特征点做了两部分工作:1个是计算前一帧的框中的特征点的光流,从而得到当前帧的特征点位置,另一个方法是直接计算当前帧的特征点,并与上一帧的特征点进行匹配,得到相匹配的特征点,然后把两个得到的特征点都融合在一起。就得到了下一帧的初步的特征点。然后在对特征点进行筛选,采用的就是上一段说的方法。

基本原理就是上面说的,下面我们从代码级别来分析一下这个算法。

3 CMT.cpp代码分析

在使用CMT算法时,我们要先初始化,也就是确定第一帧以及框框,然后进行处理下一帧。

void initialize(const Mat im_gray, const cv::Rect rect); void processFrame(const Mat im_gray);

先看初始化的代码:

void CMT::initialize(const Mat im_gray, const cv::Rect rect){//Remember initial size 存储跟踪区域的初始大小size_initial = rect.size();//Remember initial image 存储初始灰度图像im_prev = im_gray;//Compute center of rect 计算跟踪区域的中心位置Point2f center = Point2f(rect.x + rect.width/2.0, rect.y + rect.height/2.0);//Initialize detector and descriptor 初始化检测器FAST和描述器BRISKdetector = FeatureDetector::create(str_detector);descriptor = DescriptorExtractor::create(str_descriptor);//Get initial keypoints in whole image and compute their descriptorsvector<KeyPoint> keypoints;detector->detect(im_gray, keypoints); <KeyPoint> keypoints_fg;vector<KeyPoint> keypoints_bg;for (size_t i = 0; i < keypoints.size(); i++){KeyPoint k = keypoints[i];Point2f pt = k.pt;if (pt.x > rect.x && pt.y > rect.y && pt.x < rect.br().x && pt.y < rect.br().y){keypoints_fg.push_back(k);}else{keypoints_bg.push_back(k);}}//Create foreground classes 创建前景索引序号(即每个序号对应一个特征点)vector<int> classes_fg;classes_fg.reserve(keypoints_fg.size());for (size_t i = 0; i < keypoints_fg.size(); i++){classes_fg.push_back(i);}//Compute foreground/background features 计算前景和背景的特征描述Mat descs_fg;Mat descs_bg;descriptor->compute(im_gray, keypoints_fg, descs_fg);descriptor->compute(im_gray, keypoints_bg, descs_bg);//Only now is the right time to convert keypoints to points, as compute() might remove some keypoints 将关键点转换为点存储vector<Point2f> points_fg;vector<Point2f> points_bg;for (size_t i = 0; i < keypoints_fg.size(); i++){points_fg.push_back(keypoints_fg[i].pt);}for (size_t i = 0; i < keypoints_bg.size(); i++){points_bg.push_back(keypoints_bg[i].pt);}//Create normalized points 创建正规化的点,即计算前景的关键点到前景框中的相对位置作为正规化的点的坐标vector<Point2f> points_normalized;for (size_t i = 0; i < points_fg.size(); i++){points_normalized.push_back(points_fg[i] – center);}//Initialize matcher 初始化匹配器matcher.initialize(points_normalized, descs_fg, classes_fg, descs_bg, center);//Initialize consensus 初始化一致器consensus.initialize(points_normalized);//Create initial set of active keypoints 创建初始的活动点,即前景关键点的坐标for (size_t i = 0; i < keypoints_fg.size(); i++){points_active.push_back(keypoints_fg[i].pt);classes_active = classes_fg;}}临行之前,面对太多的疑问和不解:为何是一个人?

计算机视觉CV 之 CMT跟踪算法分析一

相关文章:

你感兴趣的文章:

标签云: