【问题标题】:Tracking multiple moving objects with KalmanFilter in OpenCV/C++ - How to assign tracks individually to detected objects在 OpenCV/C++ 中使用 KalmanFilter 跟踪多个移动对象 - 如何将轨迹单独分配给检测到的对象
【发布时间】:2014-12-09 09:23:39
【问题描述】:

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

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

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

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

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 是否仍然相同,如果不是,让跟踪器知道它是一个新对象与另一个分开跟踪。不确定这是否有必要或什至有用,如果有,该怎么做。

【问题讨论】:

  • 你能画一张图并在里面标记一些cmets来解释你的问题吗?分配个人 ID 没问题,但我猜你的问题是帧之间的轮廓/对象的注册?!?
  • 编辑了问题并进一步解释了问题。希望它使它更容易理解。
  • 如果你不发布你的代码很难提供帮助......我猜你正在使用“检测跟踪”?所以你用背景减法“检测”并且你只使用跟踪来“平滑”运动?您将需要使用一些真实的跟踪,其中跟踪本身识别目标的位置,独立于新目标的检测。如果你真的想使用简单的检测跟踪,你首先要对每一帧中的每个检测进行聚类(例如,检测到的对象与上一帧中最短距离的对象相同,你为每个对象创建一个跟踪器)跨度>
  • 在我搜索更多内容时再次编辑了问题。还输入一些代码来解释我的运动检测部分和卡尔曼跟踪算法。我想检测移动物体(我已经这样做了),然后进一步跟踪它们,例如用不同颜色的边界框标记它们,可能还有一个数字。请参阅我发布的示例链接,其中在 Matlab 中完成了完全相同的操作。是的,您的最后一句话可能是如何完成的(使用某种方式通过距离计算最佳匹配)。我很想有一个 c++/opencv 示例,看看我如何将它放入我的代码中。
  • 什么是boundingRect?单个轮廓或所有轮廓的 bb 的边界框?!?你只对最后一个轮廓使用卡尔曼滤波器吗?!?

标签: c++ opencv matlab-cvst kalman-filter video-tracking


【解决方案1】:

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

其他方法包括,

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

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


BoundingBoxOverlapRatio 方法:

步骤

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

    -> 比较bbox_frame2_obj1bbox_frame1_obj1bbox_frame1_obj2 等的重叠。

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

但此方法适用于包括行人检测等缓慢移动物体的场景,否则可能根本没有重叠。


匈牙利算法

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

它的工作原理如下。

创建一个矩阵,其中 作为对象的 prev_position 作为 new_detections

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

Element(1,1) -> obj_1 的质心与检测到的detection_1 之间的距离

Element(1,2) -> obj_1 的质心与检测到的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 行…

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


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

  1. Matlab 文档

  2. MATLABs Multi-Object tracker 的 C++ 实现(包括匈牙利算法)

  3. BoundingBoxOverlapRatio 方法:

  4. 匈牙利算法:

【讨论】:

    【解决方案2】:

    试试这样的:

    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
    

    【讨论】:

    • 是的,我想到目前为止我的想法几乎相同,我只是不确定如何使用 ID 部分。我想我将不得不编写另一个类来指定跟踪目标以获取分配给它的 ID。是的,跟踪可能必须在之后得到改进,但现在这就是我所需要的。我会接受你的回答,因为它可能仍然最接近我想要的。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2012-07-30
    相关资源
    最近更新 更多