8

我正在使用 OpenCV/C++ 进行实时运动检测和对象跟踪,目前卡在跟踪部分。

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

我的运动部分与 OpenCVs BackgroundSubtractor MOG2 一起使用,它可以找到轮廓并过滤掉较小的轮廓。

对于跟踪,我目前正在尝试使用 KalmanFilter(具有与此类似的实现,如果找到移动对象并在其路径上绘制一条线,则现在在每一帧中都会调用它。我的检测和跟踪部分如下所示:

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);

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

当前跟踪器获取找到对象的 x 和 y 坐标。像这样,一旦检测到另一个物体,跟踪器仍会假设它是同一个物体,但坐标与预期不同。

可以看出,没有将“轨道”分配给某个对象的功能,这可能是最大的问题。我阅读了有关匈牙利算法的信息,但不太确定如何在我的函数中实现它。

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

我的想法是,如果我对每个对象进行了唯一标识,我可以检查 ID 是否仍然相同,如果不是,则让跟踪器知道它是一个新对象,可以单独跟踪。不确定这是否有必要甚至有用,如果是的话,该怎么做。

4

2 回答 2

17

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

其他方法包括,

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

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


BoundingBoxOverlapRatio 方法:

脚步

  • Frame_1:识别 blob -> 为每个 blob 绘制 boundingRectangles bbox_frame1_obj1bbox_frame1_obj2...
  • Frame_2:识别 blob -> 绘制 boundingRectanglesbbox_frame2_obj1

    -> 比较bbox_frame2_obj1bbox_frame1_obj1等的重叠bbox_frame1_obj2

重叠的量表示是同一对象的可能性,基于哪些对象位置可以被更新。

但是这种方法适用于像行人检测这样的慢速移动物体的场景,否则可能根本没有重叠。


匈牙利算法

这种 5 到 6 步算法可作为此类分配问题的简单而稳健的解决方案。

它的工作原理如下。

创建一个矩阵,其中行为prev_position对象,列为new_detections

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

obj_1Element(1,1) -> 质心与检测到的距离detection_1

obj_1Element(1,2) -> 质心与检测到的距离detection_2...

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

5    15   30   20

20   30   3    40

12   4    15   50

这里的情况很简单直接导致结论

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)

所以 detection_4 必须是一个新对象,并且必须分配一个新的 track 和 id。

此后 obj_4 必须被跟踪,并且下一个矩阵有 4 行......</p>

但是随着对象数量的增加,任务变得更加复杂。匈牙利算法有助于解决更复杂和更大的矩阵,以便将检测优化分配给对象。


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

  1. Matlab 文档

    • 行人检测器- 提供了一种简洁的分步方法来处理多对象跟踪。
  2. MATLAB 多对象跟踪器的 C++ 实现(包括匈牙利算法)

  3. BoundingBoxOverlapRatio 方法:

  4. 匈牙利算法:

于 2016-02-23T19:17:47.500 回答
6

尝试这样的事情:

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

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

如此简单的模式:

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
于 2014-10-15T09:20:13.247 回答