在OpenCV/C++中使用KalmanFilter跟踪多个移动对象 - 如何将轨道分别分配给检测到的对象

App*_*uru 8 c++ opencv kalman-filter matlab-cvst video-tracking

我正在OpenCV/C++中进行实时运动检测和对象跟踪,目前我正处于跟踪部分.

Matlab-我想做的例子:http://www.mathworks.de/de/help/vision/examples/motion-based-multiple-object-tracking.html(我对跟踪部分感到困扰以及如何将其转移到C++/OpenCV)

我的运动部件与OpenCVs BackgroundSubtractor MOG2配合使用,可以找到轮廓并过滤掉较小的轮廓.

对于跟踪我目前正在使用卡尔曼滤波器(具有类似实施),这现在是越来越称为每一帧,如果运动物体被发现并绘制一条直线上它的路径.我的检测和跟踪部分看起来像这样:

BackgroundSubtractorMOG2 bg;
bg.operator()(frame, threshold);
bg.getBackgroundImage(background);
...  //morphological operations to remove noise etc.
findContours(threshold, ...);
...  //filtering to reject contours which are too smalle/too big

for(int i = 0; i < contours.size(); i++){
approxPolyDP(...);
boundRect = boundingRect(...);
x = boundRect.x + boundRect.width/2;
y = boundRect.y + boundRect.height/2;}

kalmanFilter.track(x,y);
kalmanFilter.draw(frame);
Run Code Online (Sandbox Code Playgroud)

当前问题: 我有一个有0个移动物体的场景,然后有1个物体移入,通过轮廓检测并被跟踪.然后第二个物体在视线中移动,被检测到并使跟踪器跳到它而不是跟随第一个或单独标记(我想要).

当前跟踪器获取找到的对象的x和y坐标.像这样,一旦检测到另一个对象,跟踪器仍假定它是相同的对象,但具有比预期的其他坐标.

可以看出,没有将"轨迹"分配给某个对象的功能,这可能是最大的问题.我读到了匈牙利算法,但我不确定如何在我的函数中实现它.

什么是使跟踪工作多个对象的好方法?

我的想法是,如果我对每个对象进行唯一识别,我可以检查ID是否仍然相同,如果没有,则让跟踪器知道它是一个与另一个分开跟踪的新对象.不确定这是否必要或甚至有用,如果是,如何做到这一点.

Sha*_*han 14

正如Micka建议您需要使用自己的算法来区分tracked_object和new_detection.最简单的解决方案是比较质心之间的距离.

其他apporaches包括,

  1. 边界框重叠率
  2. 匈牙利算法

(我最后提供了代码和文章的链接.)


BoundingBoxOverlapRatio方法:

脚步

  • Frame_1:识别blob - >为每个blob绘制boundingRectangles bbox_frame1_obj1,bbox_frame1_obj2...
  • Frame_2:识别blob - >绘制boundingRectangles bbox_frame2_obj1

    - >比较的重叠bbox_frame2_obj1bbox_frame1_obj1,bbox_frame1_obj2等.

重叠量表示基于可以更新哪些对象位置而成为同一对象的可能性.

但是这种方法适用于包括行人检测等慢速移动物体的场景,或者根本不存在重叠.


匈牙利算法

这种5到6步算法可以作为这种分配问题的简单而强大的解决方案.

它的工作原理如下.

创建一个矩阵,其中Rowsprev_position对象,Columnsnew_detections

如果我们在内存中有3个对象并且新帧有4个blob,则会产生3x4矩阵,每个元素是对象和检测之间的距离.

元素(1,1) - >质心obj_1和检测到的距离detection_1

元素(1,2) - >质心obj_1和检测到的距离detection_2......

示例矩阵(以像素为单位):

5    15   30   20

20   30   3    40

12   4    15   50
Run Code Online (Sandbox Code Playgroud)

这里的情况简单明了,导致结论

obj_1 -> detection_1   (5px between obj_1 and detection_1)
obj_2 -> detection_3   (3px between obj_2 and detection_3)
obj_3 -> detection_2   (4px between obj_3 and detection_2)
Run Code Online (Sandbox Code Playgroud)

因此,detection_4必须是新对象,并且必须分配新的轨道和id.

此后必须跟踪obj_4,下一个矩阵有4行......

但随着对象数量的增加,任务变得更加复杂.匈牙利算法有助于解决更复杂和更庞大的矩阵,以便最佳地分配对象的检测.


以下是一些用于多目标跟踪和匈牙利算法的有用资源.

  1. Matlab文档

    • 行人探测器 - 提供一种简洁的逐步方法来处理多物体跟踪.
  2. MATLABs多对象跟踪器的 C++实现(包括匈牙利算法)

  3. BoundingBoxOverlapRatio方法:

  4. 匈牙利算法:


Mic*_*cka 6

尝试这样的事情:

for each contour:
    if its already tracked with ID 'A': kalmanFilter_with_id_A.track(x,y);
    else createNewKalmanFilterWithID A
Run Code Online (Sandbox Code Playgroud)

你需要一些机制来决定它是否已被跟踪.在简单跟踪中,您只需通过测量最后一帧中轮廓的距离来确定,如果它足够接近,则它是旧对象.这是非常错误的,因此您可能希望了解更好的跟踪方法,例如概率跟踪.

如此简单的模式:

for each contour 'currentFrameC':
    for each contour 'lastFrameC'
        if distance(currentFrameC, lastFrameC) is smallest and < threshold
            currentFrameC is the same object as lastFrameC so give it the same ID
    if no shortest contour with dist < thres was found, create a new object with a new ID and create a new KalmanFilter with this same ID for that object

call kalmanFilter with ID for each found contour ID
Run Code Online (Sandbox Code Playgroud)