opencv / opencv-python

Automated CI toolchain to produce precompiled opencv-python, opencv-python-headless, opencv-contrib-python and opencv-contrib-python-headless packages.
https://pypi.org/project/opencv-python/
MIT License
4.52k stars 846 forks source link

Problem in the multitrack.update(frame) #695

Closed amunamun07 closed 2 years ago

amunamun07 commented 2 years ago
System information (version)
Detailed description

I think there is a problem in the multitrack.update(frame) section. All the bounding boxes i set initially only track one object and the other objects are ignored. Please help.

Steps to reproduce
import cv2
import sys
from random import randint

class MultipleObjectTracking:

    def __init__(self, tracker, video_path):
        self.tracker_type = tracker.upper()
        self.video_path = video_path

    def get_tracker(self):
        if self.tracker_type == "BOOSTING":
            return cv2.legacy.TrackerBoosting_create()
        elif self.tracker_type == "MIL":
            return cv2.legacy.TrackerMIL_create()
        elif self.tracker_type == "KCF":
            return cv2.legacy.TrackerKCF_create()
        elif self.tracker_type == "TLD":
            return cv2.legacy.TrackerTLD_create()
        elif self.tracker_type == "MEDIANFLOW":
            return cv2.legacy.TrackerMedianFlow_create()
        elif self.tracker_type == "MOSSE":
            return cv2.legacy.TrackerMOSSE_create()
        elif self.tracker_type == "CSRT":
            return cv2.legacy.TrackerCSRT_create()
        else:
            print("tracker not found!")
            sys.exit()

    @staticmethod
    def select_initial_bbox(frame):
        return cv2.selectROI("MultiTracker", frame)

    def get_video(self):
        video = cv2.VideoCapture(self.video_path)
        if not video.isOpened():
            print("Error while loading the video!")
            sys.exit()
        return video

    @staticmethod
    def get_bbox_color():
        color = (randint(0, 255), randint(0, 255), randint(0, 255))
        return color

    def start_tracking(self):
        tracker = self.get_tracker()
        video = self.get_video()
        bboxes = []
        bboxes_colors = []
        ok, first_frame = video.read()
        if not ok:
            print("Error while loading the frame!")
            sys.exit()
        while True:
            bbox = self.select_initial_bbox(first_frame)
            bboxes.append(bbox)
            bboxes_colors.append(self.get_bbox_color())
            print("Press Q to quit and start the tracking")
            print("Press Any other key to select next object")
            k = cv2.waitKey(0) & 0xFF
            if k == 113:
                break
        multi_tracker = cv2.legacy.MultiTracker_create()
        for b in bboxes:
            multi_tracker.add(tracker, first_frame, b)
        while video.isOpened():
            ok, frame = video.read()
            if not ok:
                break
            ok, boxes = multi_tracker.update(frame)
            print(boxes)
            for i, newbox in enumerate(boxes):
                p1 = (int(newbox[0]), int(newbox[1]))
                p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3]))
                cv2.rectangle(frame, p1, p2, bboxes_colors[i], 2, 1)

            cv2.imshow("MultiTracker", frame)
            if cv2.waitKey(1) & 0xFF == 27:
                break
amunamun07 commented 2 years ago

Run "python main.py --video [video_path]"

import argparse
from centroid.single_object_tracking import SingleObjectTracking
from centroid.multiple_object_tracking import MultipleObjectTracking

def main(args):
    args = parse_args(args)
    if args.mode.lower() == "single":
        parser = SingleObjectTracking(args.tracker, args.video)
        parser.start_tracking()
    if args.mode.lower() == "multiple":
        parser = MultipleObjectTracking(args.tracker, args.video)
        parser.start_tracking()

def parse_args(args):
    parser = argparse.ArgumentParser(description='For Object Tracking')
    parser.add_argument('--mode', help='Single or Multiple', default="multiple")
    parser.add_argument('--tracker', help='The Tracking Algorithm', default="boosting")
    parser.add_argument('--video', help='Path to the Video', required=True)
    return parser.parse_args(args)

if __name__ == '__main__':
    import sys
    main(sys.argv[1:])
asmorkalov commented 2 years ago

tracker = self.get_tracker() - it's an object of cv::legacy::Tracker on C++ side. It's capable to track single object only. You feed all bounding boxes for different objects to single instance. It breaks tracker behavior. You need to create separate Tracker instance for each tracked object.