使用OpenCV/C++中的Kalman滤波器跟踪多个移动对象-如何将轨迹分配给检测到的对象

8
我正在使用OpenCV/C++进行实时运动检测和物体跟踪,目前在跟踪部分遇到了困难。
我想做的事情可以用Matlab示例来说明:http://www.mathworks.de/de/help/vision/examples/motion-based-multiple-object-tracking.html(我在跟踪部分以及如何将其转换为C++/OpenCV方面遇到了麻烦)。
我的运动部分使用了OpenCV的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);

当前问题: 我有一个场景,没有任何动态物体,然后一个物体移动进来,通过轮廓被检测到并被跟踪。随后第二个物体出现在视野中,被检测到,但跟踪器跳到了它上面,而不是继续跟踪第一个物体或者标记两个物体(我想要的)。
目前的跟踪器记录了被发现物体的x和y坐标。因此,一旦另一个物体被发现,跟踪器仍会假设它是同一个物体,只是有其他预期之外的坐标。
正如大家所见,最大的问题可能是没有“将跟踪与特定物体关联”的功能。我阅读了匈牙利算法,但不太确定如何在我的函数中实现它。
那么,有什么好的方法可以让跟踪同时适用于多个物体呢?
我的想法是,如果我能够为每个物体分配唯一的标识符,我就可以检查ID是否仍相同,如果不同,就让跟踪器知道这是一个新物体,需要单独跟踪。但我不确定这是否必要或者有用,如果需要,该如何实现。

你能画一张图片并在里面标注一些注释来解释你的问题吗?分配单独的ID不是问题,但我猜你的问题是在帧之间注册轮廓/对象?!? - Micka
修改了问题并进一步解释了问题。希望这样更容易理解。 - Appuru
如果您不发布您的代码,那么很难提供帮助...我猜您正在使用“跟踪检测”?因此,您使用背景减法进行“检测”,并且仅使用跟踪来“平滑”移动?您将想要使用一些真正的跟踪,其中跟踪本身独立于新目标的检测来识别目标的位置。如果您真的想使用简单的跟踪检测,则首先需要在每个帧中对每个检测进行聚类(例如,检测到的对象与上一帧中最短距离对象相同,并为每个对象创建一个跟踪器)。 - Micka
@Appuru 你好,你做完了吗?你是如何将卡尔曼滤波器分配给每个质心的?我也卡在这里了。 - Dr. Mallikarjun Anandhalli
嘿,就像Micka在他的回答中所说的那样。每当发现一个新的质心时,都会创建一个新的卡尔曼滤波器。这意味着我会根据特定条件创建和删除对象,并在创建新对象时创建新的KF。 - Appuru
显示剩余3条评论
1个回答

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

是的,我想我的想法到目前为止基本上也差不多,只是不确定如何处理ID部分。我猜我得写另一个类来指定跟踪目标以分配ID。是的,跟踪可能需要在之后进行改进,但现在这就是我所需要的。我会接受你的答案,因为它可能仍然是我想要的最接近的答案。 感谢你的帮助。 - Appuru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接