1

I'm in the early stages (VERY alpha) of writing the backend for an open source home video surveillance system. I'm building it on Gstreamer as a series of plugins. The idea is going to make each step of the process modular based on implementations, so that anyone can write a custom module and use that in the pipeline. For an example, take a look at "odo-lib-opencv-yolo" in the repo linked below. Using that as a template, anyone can write their own detection lib using any library or neural network model as use it within this pipeline. I also plan to expand that out to include a few "default" libraries that are optimized for different systems (Nvidia GPUs, Raspberry Pis, Coral TPUs, etc).

The issue I'm running into is the tracking portion. I wanted to start off with a simple and basic tracking system using the tracking API in OpenCV as a "filler" while I flesh out everything else. But it just doesn't seem to work right.

Here's the link to the repo: https://github.com/CeeBeeEh/Odo-Project

Of most importance is this code block in gst/gstodotrack.cpp at line 270:

if (meta->isInferenceFrame) {
    LAST_COUNT = meta->detectionCount;
    TRACKER->clear();
    TRACKER = cv::legacy::MultiTracker::create();
    for (int i=0; i<LAST_COUNT; i++) {
        LAST_DETECTION[i].class_id = meta->detections[i].class_id;
        LAST_DETECTION[i].confidence = meta->detections[i].confidence;
        strcpy(LAST_DETECTION[i].label, meta->detections[i].label);
        cv::Rect2i rect = cv::Rect2i(meta->detections[i].box.x, meta->detections[i].box.y,
                                     meta->detections[i].box.width, meta->detections[i].box.height);
        TRACKER->add(create_cvtracker(odo), img, rect);
    }
    GST_DEBUG("Added %zu objects to tracker", LAST_COUNT);
}
else {
    meta->detectionCount = LAST_COUNT;

    std::vector<cv::Rect2d> tracked;
    if (!TRACKER->update(img, tracked)) GST_ERROR("Error tracking objects");

    GST_DEBUG("Infer count=%lu, tracked count=%zu", LAST_COUNT, tracked.size());

    for (int i=0; i<tracked.size(); i++) {
        meta->detections[i].box.x = tracked[i].x;
        meta->detections[i].box.y = tracked[i].y;
        meta->detections[i].box.width = tracked[i].width;
        meta->detections[i].box.height = tracked[i].height;
        meta->detections[i].class_id = LAST_DETECTION[i].class_id;
        meta->detections[i].confidence = LAST_DETECTION[i].confidence;
        strcpy(meta->detections[i].label, LAST_DETECTION[i].label);
    }
}

Variables at top of file:

cv::Ptr<cv::legacy::MultiTracker> TRACKER;
ulong LAST_COUNT = 0;
DetectionData LAST_DETECTION[DETECTION_MAX] = {};

I originally had

TRACKER = cv::legacy::MultiTracker::create();

in the start method to create it when the plugin is loaded, but that caused a segfault.

I've also tried creating a fixed size array of cv::Ptr<cv::Tracker> and just use each one for a single object with the same id within each frame, and then recycle each one for each inference frame. But that cause odd behaviour with each object was tracking to the same size and position within the frame.

Right now, in the current configuration, the tracking is dog-slow. It's actually faster to just inference each frame on GPU than inference a single frame and track for x additional frames. It should be the opposite.

It seems as though OpenCV's tracking API has changed as of 4.5.1, but I'm not sure if that's the cause of the issue.

I'm looking for help in sorting out the OpenCV tracking issue. I find all the docs very lacking in explaining the what and why of the multi-tracking API. So those are not of much help.

Chris
  • 538
  • 2
  • 8
  • 20
  • I'm guessing "odo" has nothing to do with *odo*metry but with a snarky someone that is kinda liquid sometimes -- don't expect too much of OpenCV's "multitracker" stuff. that came out of a Google Summer of Code project and has probably _not_ been maintained since then. if it lives in the `contrib` repo, it's very "at your own risk". in fact, nobody's bothering with any of these tracking APIs some individuals thought to put into OpenCV. everyone's just using DNNs for the task, and writing their own logic on top of that. – Christoph Rackwitz Aug 25 '22 at 19:34
  • @ChristophRackwitz haha, yes it does have to do with a liquidy person that never misses anything that happens around him. I thought it was a good name. What you've said has validated what I've been thinking about the state of the code - "unmaintained". I was hoping I had missed something, but I guess I'll need to ditch it. Unfortunately, I don't think there's any available libraries to do what I'm looking for. The only one I've worked with that I like the results of is nvtracker from Nvidia's DeepStream SDK, but that's entirely dependant on Nvidia hardware. Thanks for the input. – Chris Aug 25 '22 at 21:11
  • this is a sample of one dnn-based tracker: https://github.com/opencv/opencv/blob/4.x/samples/dnn/dasiamrpn_tracker.cpp – Christoph Rackwitz Aug 25 '22 at 22:29

0 Answers0