based Matching and Tracking of Keypoints for Object Tracking

基于特征点的目标跟踪算法,加入了投票算法,原理比较简单,算法流程如图所示。

Step1:在样本图像检测Keypoint,根据人工选择的区域划分前景Keypoint与背景Keypoint,分别计算相应的描述子descriptor,存储在feature的数据库的矩阵中。Step2:给前景Keypoint分配从1开始的序列号,给背景Keypoint分配成统一的0序列号。并将它们存在class分类(前景)数据库的向量(矩阵)中。同时Keypoint中包含该点图像中的绝对坐标系中的位置。Step3:进入循环(主要是初步选取活动的Keypoint和根据评估投票结果精选Keypoint和一些运动信息)Step4: 初选Keypoint分为Track和Match的两个过程:(实际代码中与上述算法有所出入,这里先讲述上述算法)在当前图像帧中检测Keypoint;Step5:计算当前Keypoint与样本图像中的所有Keypoint(含前景与背景)的特征的距离或等同量,特征匹配程度较高的Keypoint作为Active Keypoint,即有效Keypoint。Step6:Track 过程:光流法计算相邻图像帧的关键点移动情况,倘若前向计算与后向计算结果相差不大且没有离开图像视野,则认为该点为active Keypoint;Step7:合并上述的active Keypoint;Step8: 根据Active Keypoint之间的距离和相应的样本中Keypoint之间的距离的比例,计算相应的尺寸变化的比例向量,取其中值。Step9:类似的得到旋转角度。Step10:根据样本Keypoint与目标中心之间的偏移,和已得到的尺寸变化,角度变化,将Active Keypoint的坐标点转换成新目标(待选)中心点(由于Active Keypoint可能产生错动,转换成新的对应目标中心点亦存在偏差,这正是引入投票决策的原因)Step11-14:基于大部分Keypoint偏差较小的假设,因此大部分目标(待选)中心点都会指向实际中心附近,因此它们会聚集在较小的区域。这里采用自下而上的聚类的方法,将待选中心点聚类。其中某类数目最多而且占总体比例较高,则认为该类是指向实际新中心附近的,计算它们的中心,认为新的目标中心点。Step15:根据新的目标中心点和之前得到的变形参数,确定新的目标边界。Step11-14中自下而上的聚类方法和统计各类参数等处的编程代码质量较高。粘出来

//该段函数主要用于将坐标点集合根据之间的距离大小聚类std::vector<Cluster> linkage(const std::vector<cv::Point2f>& list){float inf = 10000000;0;std::vector<bool> used;for(int i = 0; i < 2*list.size(); i++)used.push_back(false);std::vector<std::vector<float> > dist;//以下实际构建2n*2n的矩阵(其中n为数据点数目)//其中只有n*n的左上角的矩阵块存储了两个点的之间的距离,由于坐标点本身之间不存在聚类,不纳入考虑范围之内,//因此对角线上的元素为无穷大(我们要在矩阵中不断寻找最小距离然后聚类,因此无穷大可以避免这种原本不存在的情况)for(int i = 0; i < list.size(); i++){std::vector<float> line;for(int j = 0; j < list.size(); j++){if(i == j)line.push_back(inf);else{cv::Point2f p = list[i]-list[j];line.push_back(sqrt(p.dot(p)));}}for(int j = 0; j < list.size(); j++)line.push_back(inf);dist.push_back(line);}for(int i = 0; i < list.size(); i++){std::vector<float> line;for(int j = 0; j < 2*list.size(); j++)line.push_back(inf);dist.push_back(line);}//下面进行正式聚类,,这一段要和findMinSymetric子函数一起看。//主要思想为:以第一次聚类来看,取当前矩阵中的中最小的距离的两个点作为一类,一旦作为一类之后,原先的距离矩阵的距离立即作废,标记为used,同时计算其他的点到该类中的最小距离(这里该类只有两个点,即两个距离中的较小值),而这两个点到该类的距离应再次标为无穷大。这也是为什么事先给的距离矩阵是个2n*2n的矩阵的原因,用于存储类与类(或者点与类的距离),每次只能减少一个点或者一个类,这样总共需要减少n次才能将所有点聚类。同时记录该类中数目,用于将来比较。std::vector<Cluster> clusters;while(clusters.size() < list.size()-1){int x, y;float min = findMinSymetric(dist, used, list.size()+clusters.size(), x, y);Cluster cluster;cluster.first = x;cluster.second = y;cluster.dist = min;cluster.num = (x < list.size() ? 1 : clusters[x-list.size()].num) + (y < list.size() ? 1 : clusters[y-list.size()].num);used[x] = true;used[y] = true;int limit = list.size()+clusters.size();for(int i = 0; i < limit; i++){if(!used[i])dist[i][limit] = dist[limit][i] = std::min(dist[i][x], dist[i][y]);}clusters.push_back(cluster);}return clusters;}<pre name="code" class="cpp">float findMinSymetric(const std::vector<std::vector<float> >& dist, const std::vector<bool>& used, int limit, int &i, int &j){float min = dist[0][0];i = 0;j = 0;for(int x = 0; x < limit; x++){if(!used[x]){for(int y = x+1; y < limit; y++)if(!used[y] && dist[x][y] <= min){min = dist[x][y];i = x;j = y;}}}return min;}//根据要求的距离阈值,对坐标点标记类的ID号,思想为:往每一个数据点上挨个标记ID,距离过近的两类认为是同一类。这里使用了递归的方法,递归的目的寻找所有的坐标点void fcluster_rec(std::vector<int>& data, const std::vector<Cluster>& clusters, float threshold, const Cluster& currentCluster, int& binId){int startBin = binId;if(currentCluster.first >= data.size())fcluster_rec(data, clusters, threshold, clusters[currentCluster.first – data.size()], binId);else data[currentCluster.first] = binId;if(startBin == binId && currentCluster.dist >= threshold)binId++;startBin = binId;if(currentCluster.second >= data.size())fcluster_rec(data, clusters, threshold, clusters[currentCluster.second – data.size()], binId);else data[currentCluster.second] = binId;if(startBin == binId && currentCluster.dist >= threshold)binId++;}std::vector<int> fcluster(const std::vector<Cluster>& clusters, float threshold){std::vector<int> data;for(int i = 0; i < clusters.size()+1; i++)data.push_back(0);int binId = 0;fcluster_rec(data, clusters, threshold, clusters[clusters.size()-1], binId);return data;}std::vector<int> binCount(const std::vector<int>& T){std::vector<int> result;for(int i = 0; i < T.size(); i++){while(T[i] >= result.size())result.push_back(0);result[T[i]]++;}return result;}

孤单寂寞与被遗弃感是最可怕的贫穷

based Matching and Tracking of Keypoints for Object Tracking

相关文章:

你感兴趣的文章:

标签云: