Smorodov / Multitarget-tracker

Multiple Object Tracker, Based on Hungarian algorithm + Kalman filter.
Apache License 2.0
2.17k stars 647 forks source link

It is possible to have a Track Id from the first frame of the detection?? #189

Open isra60 opened 4 years ago

isra60 commented 4 years ago

Maybe is better to understand with this video.

https://drive.google.com/file/d/108rmnPphciZsu6GlSLcI7xpWh9QGWKMO/view?usp=sharing

How can i get the same track id for every car instead of different ids??

TrackerSettings settings; settings.SetDistance(tracking::DistCenters); settings.m_kalmanType = tracking::KalmanLinear; settings.m_filterGoal = tracking::FilterCenter; // Use visual objects tracker for collisions resolving settings.m_matchType = tracking::MatchHungrian; settings.m_dt = 0.2f; // Delta time for Kalman filter settings.m_accelNoiseMag = 0.2f; // Accel noise magnitude for Kalman filter settings.m_distThres = 0.8f;

Nuzhny007 commented 4 years ago

Hi! For big and fast objects will be better: tracking::DistJaccard and m_distThres = 0.4f;

isra60 commented 4 years ago

I'm triying with this parameters and still is the same behaviour...

if I increase the distThresh i get better result

And also from traffic videos like this? Which will be the better parameters??

https://www.youtube.com/watch?v=GCj8x7ou-U8

Nuzhny007 commented 4 years ago

Result: https://www.dropbox.com/s/uwra0tgtdllgfc2/traffic.mp4?dl=0

Command line:

MultitargetTracker.exe "D:\Dropbox\Public\London Road Traffic England A3 near M25 Heavy Traffic, cars.webm" -e=6 -g=0 -a=1 -o=traffic.mp4

Code:

bool InitDetector(cv::UMat frame)
    {
        config_t config;

#ifdef _WIN32
        std::string pathToModel = "../../data/";
#else
        std::string pathToModel = "../data/";
#endif
#if 0
        config.emplace("modelConfiguration", pathToModel + "yolov3-tiny.cfg");
        config.emplace("modelBinary", pathToModel + "yolov3-tiny.weights");
        config.emplace("confidenceThreshold", "0.5");
#else
        config.emplace("modelConfiguration", pathToModel + "yolov3.cfg");
        config.emplace("modelBinary", pathToModel + "yolov3.weights");
        config.emplace("confidenceThreshold", "0.7");
#endif
        config.emplace("classNames", pathToModel + "coco.names");
        config.emplace("maxCropRatio", "-1");

        config.emplace("white_list", "person");
        config.emplace("white_list", "car");
        config.emplace("white_list", "bicycle");
        config.emplace("white_list", "motorbike");
        config.emplace("white_list", "bus");
        config.emplace("white_list", "truck");
        //config.emplace("white_list", "traffic light");
        //config.emplace("white_list", "stop sign");

        m_detector = std::unique_ptr<BaseDetector>(CreateDetector(tracking::Detectors::Yolo_Darknet, config, frame));
        if (m_detector.get())
        {
            m_detector->SetMinObjectSize(cv::Size(frame.cols / 40, frame.rows / 40));
            return true;
        }
        return false;
    }

    bool InitTracker(cv::UMat frame)
    {
        TrackerSettings settings;
        settings.SetDistance(tracking::DistJaccard);
        settings.m_kalmanType = tracking::KalmanLinear;
        settings.m_filterGoal = tracking::FilterCenter;
        settings.m_lostTrackType = tracking::TrackSTAPLE;      // Use visual objects tracker for collisions resolving
        settings.m_matchType = tracking::MatchHungrian;
        settings.m_dt = 0.3f;                                // Delta time for Kalman filter
        settings.m_accelNoiseMag = 0.2f;                     // Accel noise magnitude for Kalman filter
        settings.m_distThres = 0.7f;                         // Distance threshold between region and object on two frames
        settings.m_minAreaRadius = frame.rows / 20.f;
        settings.m_maximumAllowedSkippedFrames = cvRound(2 * m_fps); // Maximum allowed skipped frames
        settings.m_maxTraceLength = cvRound(3 * m_fps);      // Maximum trace length

        settings.AddNearTypes("car", "bus", false);
        settings.AddNearTypes("car", "truck", false);
        settings.AddNearTypes("person", "bicycle", true);
        settings.AddNearTypes("person", "motorbike", true);

        m_tracker = std::make_unique<CTracker>(settings);

        return true;
    }

    void DrawData(cv::Mat frame, int framesCounter, int currTime)
    {
        auto tracks = m_tracker->GetTracks();

        if (m_showLogs)
        {
            std::cout << "Frame " << framesCounter << ": tracks = " << tracks.size() << ", time = " << currTime << std::endl;
        }

        for (const auto& track : tracks)
        {
            if (track.IsRobust(5,                           // Minimal trajectory size
                0.8f,                        // Minimal ratio raw_trajectory_points / trajectory_lenght
                cv::Size2f(0.1f, 8.0f))      // Min and max ratio: width / height
                )
            {
                DrawTrack(frame, 1, track);

                std::stringstream label;
                label << track.m_type << " " << std::setprecision(2) << track.m_velocity << ": " << track.m_confidence;
                int baseLine = 0;
                cv::Size labelSize = cv::getTextSize(label.str(), cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);

                cv::Rect brect = track.m_rrect.boundingRect();
                if (brect.x < 0)
                {
                    brect.width = std::min(brect.width, frame.cols - 1);
                    brect.x = 0;
                }
                else if (brect.x + brect.width >= frame.cols)
                {
                    brect.x = std::max(0, frame.cols - brect.width - 1);
                    brect.width = std::min(brect.width, frame.cols - 1);
                }
                if (brect.y - labelSize.height < 0)
                {
                    brect.height = std::min(brect.height, frame.rows - 1);
                    brect.y = labelSize.height;
                }
                else if (brect.y + brect.height >= frame.rows)
                {
                    brect.y = std::max(0, frame.rows - brect.height - 1);
                    brect.height = std::min(brect.height, frame.rows - 1);
                }
                DrawFilledRect(frame, cv::Rect(cv::Point(brect.x, brect.y - labelSize.height), cv::Size(labelSize.width, labelSize.height + baseLine)), cv::Scalar(200, 200, 200), 150);
                cv::putText(frame, label.str(), brect.tl(), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
            }
        }
    }
Nuzhny007 commented 4 years ago

@isra60 I'm added a new option - m_minAreaRadiusK for best tracking objects on scene with perspective. If m_minAreaRadiusPix < 0 then m_minAreaRadiusK used for calculation minimal ellipse around objects center. It's good for far and for near objects. Example: https://github.com/Smorodov/Multitarget-tracker/blob/master/example/examples.h#L661

And you can read more in our Wiki: https://github.com/Smorodov/Multitarget-tracker/wiki/Fine-tuning-TrackerSettings Smorodov and I are writing in first in russian but you can translate it.

scianand commented 4 years ago

Hi @Nuzhny007,

I want to access the id of the object like person1, person2, person3 and their traced path. Please can you tell me how can I do that?

Thanks

Nuzhny007 commented 4 years ago

Hi! All information about tracks you can take as in function DrawData: https://github.com/Smorodov/Multitarget-tracker/blob/master/example/examples.h#L699 Each track has a string type name and unique numeric id. It's not person1, person2, etc. But: object1 with type "person", object 123 with type "car", ..., object N with type "bus"

scianand commented 4 years ago

Hi @Nuzhny007,

Thank you so much.

scianand commented 4 years ago

Hi @Nuzhny007,

Please can you suggest me how can I change the minimum numbers of detection to initiate a track? Currently, the track is initiated and objects id assigned after 3 detections. How can I change that?

Thanks,

Nuzhny007 commented 4 years ago

the first param in function IsRobust: https://github.com/Smorodov/Multitarget-tracker/blob/master/example/examples.h#L710