Project-MultiObjectTracking

概述

  这个是我们数字图像处理课程的一个project。要求用yolo模型得到视频中行人的bounding-box,然后再得到每个行人的行走轨迹。其中yolo模型输出的bounding-box输出到txt中,然后再对txt中bounding-box数据进行处理,得到每个行人的轨迹。

相关知识

yolo-v3模型

  yolo是一个实现object-detection的网络,其原理和实现参考yolo.
  需要说明的是,yolo输出的bounding-box用四个参数表示(x,y,w,h)。每个参数都是以原图像size的比例输出的,因此使用的时候应该注意其坐标系与大小的转换。

思路整理

  其实这个问题由两部分组成,为object-detection和multi-object-tracking。其中本次project主要试验和学习的是multi-object-tracking部分。object-detection部分我直接使用了yolo实现,由于这份code里实现的是单帧的object-detection,所以我写了一个shell代码批处理了一个视频文件中的所有帧,就得到了一个object-detection之后的视频和一个记录每帧bounding-box信息的txt文件。
  在实现multi-object-tracking部分的时候,首先要明确measure和tracker两个概念。measure即为每个检测出来的bounding-box,而tracker则为跟踪一个运动的人的模型,我们需要做的是将每个出现的measure划分到正确的tracker中,然后画出每个tracker的轨迹即可。为了便于实现,我选择了bounding-box的list为每个tracker组成,最临近的bounding-box为这个tracker的特征。
  实现单一measure和tracker匹配的主要思路是利用measure的bounding-box和tracker的特征bounding-box的相交的面积进行匹配。我设定了一个最小相交比例的阈值,如果两个bounding-box的相交大于这个阈值,则说明这个measure可以和这个tracker相匹配,如果小鱼这个阈值,则不能匹配。
  实现每一帧匹配的思路是measure和tracker的双向选择。选择匹配算法,然后先用当前帧中measure-list匹配一遍tracker-list找最大,然后再用tracker-list去匹配一遍measure-list找最大,如果出来两者相互匹配,则将measure划分到该tracker中,如果不能匹配,则将measure先作为一个暂时的tracker,然后再处理几帧,判断这个暂时的tracker是保留还是删除。
  最后再把当前每个tracker画出即可。

代码实现

实现框架

  由于测试样例情况不是很复制,因为我仅采用的用measure去匹配当前tracker的算法,相关尚可,其中只要使用的函数包括一下函数

  • read_box_location(box_dir):读取并处理bounding-box数据,主要进行的是字符串的处理工作,得到box_video为已经划分好的每帧的bounding-box
  • get_box_area(box,video_size):计算单一bounding-box的面积
  • whether_intersect(box1,box2,video_size):判断两个bounding-box是否相交
  • get_overlapping_area(box1,box2,video_size):计算两个bounding-box的相交面积,主要利用4个参数在坐标系上推导得到
  • tracker_initialization(box_video):tracker的初始化
  • one_measure_to_tracker(trackers_list,measure,video_size):实现一个measure到当前tracker的匹配
  • frame_measure_to_tracker(trackers_list,measure_list,video_size):实现一帧中所有measure的匹配
  • add_measure_to_trackers(trackers_list,box_video,frame_index,video_size):添加每帧的measure到tracker中

完整实现

  代码的实现可以参看我的github:SuperYanyann/multiObjectTracking

效果

  主要要三个测试用例,但是第2个测试用例当时拍的不是很好,角度太低导致人的重叠面积代码,效果不是很好,另外两个效果尚可。我取最后一帧来展示测试结果如下:
  test1:
                      photo1
  test2:
                      photo2
  test3:
                      photo1

小结

  这此的project写的思路还是挺明确的,就是一开始没有找到合适表示每个tracker的方法,我一开始想的是存储每个bounding-box的center来表示tracker,这样便于画路径,但是这样写的比较乱,即有bounding的list也有center的list。然后重构了一下代码,整体用bounding-box来作为tracker特征,然后直接利用box进行路径的匹配,将计算center的工作封装到了函数中,这样结构下代码写起来就流畅了许多。感觉之后再写数据比较复杂的代码时候,还是应该想想好相应的存储结构,整体规划好代码的结构后再开始写,磨刀不误砍柴工