예제 #1
0
    def __init__(self, opt, polygon, paths, polygon2=None, frame_rate=30):
        self.opt = opt
        if opt.gpus[0] >= 0:
            opt.device = torch.device('cuda')
        else:
            opt.device = torch.device('cpu')
        print('Creating model...')
        anchor_ratios = [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)]
        anchor_scales = [2**0, 2**(1.0 / 3.0), 2**(2.0 / 3.0)]
        input_sizes = [512, 640, 768, 896, 1024, 1280, 1280, 1536]
        self.input_size = input_sizes[opt.compound_coef]
        self.obj_list = [
            'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
            'train', 'truck', 'boat', 'traffic light', 'fire hydrant', '',
            'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',
            'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe',
            '', 'backpack', 'umbrella', '', '', 'handbag', 'tie', 'suitcase',
            'frisbee', 'skis', 'snowboard', 'sports ball', 'kite',
            'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
            'tennis racket', 'bottle', '', 'wine glass', 'cup', 'fork',
            'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
            'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair',
            'couch', 'potted plant', 'bed', '', 'dining table', '', '',
            'toilet', '', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',
            'cell phone', 'microwave', 'oven', 'toaster', 'sink',
            'refrigerator', '', 'book', 'clock', 'vase', 'scissors',
            'teddy bear', 'hair drier', 'toothbrush'
        ]
        self.person_or_motorcycle = ['motorcycle', 'bicycle']
        self.obj_interest = [
            'motorcycle', 'bicycle', 'bus', 'truck', 'car'
        ] if self.person_or_motorcycle[0] != 'person' else [
            'person', 'bus', 'truck', 'car'
        ]
        print(self.obj_interest)
        self.detetection_model = EfficientDetBackbone(
            compound_coef=opt.compound_coef,
            num_classes=len(self.obj_list),
            ratios=anchor_ratios,
            scales=anchor_scales)

        self.detetection_model.load_state_dict(
            torch.load(
                f'EfficientDet/weights/efficientdet-d{opt.compound_coef}.pth'))
        self.detetection_model.eval()
        device = torch.device('cuda:0')
        self.detetection_model = self.detetection_model.to(device)

        self.tracked_stracks = []  # type: list[STrack]
        self.lost_stracks = []  # type: list[STrack]
        self.removed_stracks = []  # type: list[STrack]

        self.frame_id = 0
        self.det_thresh = opt.conf_thres
        self.buffer_size = int(frame_rate / 30.0 * opt.track_buffer)
        self.max_time_lost = self.buffer_size
        self.max_per_image = opt.K

        self.kalman_filter = KalmanFilter()

        self.polygon = polygon
        self.paths = paths
        self.polygon2 = polygon2
        self.line2 = [self.polygon[1], self.polygon[2]]
        self.line1 = [self.polygon[4], self.polygon[3]] if len(
            self.polygon) == 5 else [self.polygon[0], self.polygon[3]] if len(
                self.polygon) == 4 else None
        self.two_polygon_system = False
        self.warmup_frame = 6 if self.two_polygon_system else 0
        self.virtual_polygon = [[0, 573], [0, 109], [1270, 109], [1270, 573]]
예제 #2
0
    def __init__(self, opt,polygon, paths, polygon2=None,frame_rate=30):
        self.opt = opt
        if opt.gpus[0] >= 0:
            opt.device = torch.device('cuda')
        else:
            opt.device = torch.device('cpu')
        print('Creating model...')
        anchor_ratios = [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)]
        anchor_scales = [2 ** 0, 2 ** (1.0 / 3.0), 2 ** (2.0 / 3.0)]
        input_sizes = [512, 640, 768, 896, 1024, 1280, 1280, 1536]
        self.input_size = input_sizes[opt.compound_coef] 
        if opt.detection_model=='Efficient' :
            self.obj_list =['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
                'fire hydrant', '', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep',
                'cow', 'elephant', 'bear', 'zebra', 'giraffe', '', 'backpack', 'umbrella', '', '', 'handbag', 'tie',
                'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove',
                'skateboard', 'surfboard', 'tennis racket', 'bottle', '', 'wine glass', 'cup', 'fork', 'knife', 'spoon',
                'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut',
                'cake', 'chair', 'couch', 'potted plant', 'bed', '', 'dining table', '', '', 'toilet', '', 'tv',
                'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink',
                'refrigerator', '', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier',
                'toothbrush']
            self.person_or_motorcycle=['person']
            self.obj_interest=[ 'motorcycle','bicycle', 'bus', 'truck','car'] if self.person_or_motorcycle[0]!='person' else [ 'person', 'bus', 'truck','car']
            self.detetection_model= EfficientDetBackbone(compound_coef=opt.compound_coef, num_classes=len(self.obj_list),
                                ratios=anchor_ratios, scales=anchor_scales)
        
            self.detetection_model.load_state_dict(torch.load(f'EfficientDet/weights/efficientdet-d{opt.compound_coef}.pth'))
            self.detetection_model.eval()
            device = torch.device('cuda:0')
            self.detetection_model = self.detetection_model.to(device)
        elif  opt.detection_model=='FasterRcnn' :
            config_file = "Drone_FasterRCNN/drone_demo/e2e_faster_rcnn_X_101_32x8d_FPN_1x_visdrone.yaml"
            cfg.merge_from_file(config_file)
            cfg.merge_from_list(["MODEL.WEIGHT", "Drone_FasterRCNN/drone_demo/visdrone_model_0360000.pth"])
            self.detetection_model = COCODemo(
                cfg,
                min_image_size=opt.min_img_size,
                confidence_threshold=opt.conf_thres,
            )
            label_of_interest=[
                    # "__background",
                    # "unused",
                    # "pedestrian",
                    # "person",
                    # "bicycle",
                    "car",
                    "van",
                    "truck",
                    # "tricycle",
                    # "awning-tricycle",
                    "bus",
                    "motor"
            ]
            self.person_or_motorcycle=["motor"]
            #'bicycle'
            self.obj_interest=[ 'motor', 'bus', 'truck','car','van', "tricycle"] if self.person_or_motorcycle[0]!='person' else [ 'person', 'bus', 'truck','car','van', "tricycle"]
        else:
            raise('Not supported detector model')

        self.tracked_stracks = []  # type: list[STrack]
        self.lost_stracks = []  # type: list[STrack]
        self.removed_stracks = []  # type: list[STrack]

        self.frame_id = 0
        self.det_thresh = opt.conf_thres
        self.buffer_size = int(frame_rate / 30.0 * opt.track_buffer)
        self.max_time_lost = self.buffer_size
        self.max_per_image = opt.K

        self.kalman_filter = KalmanFilter()

        self.polygon=polygon
        self.paths=paths
        self.polygon2=polygon2
        self.line1=[polygon[0],polygon[1]]
        self.line2=[polygon[1],polygon[2]]
        self.line3=[polygon[2],polygon[3]]
        self.line4=[polygon[0],polygon[4]]
        self.two_polygon_system=True
        self.warmup_frame=0 
        self.virtual_polygon= [
                [
                    0,
                    680
                ],
                [
                    0,
                    149
                ],
                [
                    1270,
                    149
                ],
                [
                    1270,
                    680
                ]
            ]
예제 #3
0
class JDETracker(object):
    def __init__(self, opt, polygon, paths, polygon2=None, frame_rate=30):
        self.opt = opt
        if opt.gpus[0] >= 0:
            opt.device = torch.device('cuda')
        else:
            opt.device = torch.device('cpu')
        print('Creating model...')
        anchor_ratios = [(1.0, 1.0), (1.4, 0.7), (0.7, 1.4)]
        anchor_scales = [2**0, 2**(1.0 / 3.0), 2**(2.0 / 3.0)]
        input_sizes = [512, 640, 768, 896, 1024, 1280, 1280, 1536]
        self.input_size = input_sizes[opt.compound_coef]
        self.obj_list = [
            'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
            'train', 'truck', 'boat', 'traffic light', 'fire hydrant', '',
            'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',
            'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe',
            '', 'backpack', 'umbrella', '', '', 'handbag', 'tie', 'suitcase',
            'frisbee', 'skis', 'snowboard', 'sports ball', 'kite',
            'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
            'tennis racket', 'bottle', '', 'wine glass', 'cup', 'fork',
            'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
            'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair',
            'couch', 'potted plant', 'bed', '', 'dining table', '', '',
            'toilet', '', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',
            'cell phone', 'microwave', 'oven', 'toaster', 'sink',
            'refrigerator', '', 'book', 'clock', 'vase', 'scissors',
            'teddy bear', 'hair drier', 'toothbrush'
        ]
        self.person_or_motorcycle = ['motorcycle', 'bicycle']
        self.obj_interest = [
            'motorcycle', 'bicycle', 'bus', 'truck', 'car'
        ] if self.person_or_motorcycle[0] != 'person' else [
            'person', 'bus', 'truck', 'car'
        ]
        print(self.obj_interest)
        self.detetection_model = EfficientDetBackbone(
            compound_coef=opt.compound_coef,
            num_classes=len(self.obj_list),
            ratios=anchor_ratios,
            scales=anchor_scales)

        self.detetection_model.load_state_dict(
            torch.load(
                f'EfficientDet/weights/efficientdet-d{opt.compound_coef}.pth'))
        self.detetection_model.eval()
        device = torch.device('cuda:0')
        self.detetection_model = self.detetection_model.to(device)

        self.tracked_stracks = []  # type: list[STrack]
        self.lost_stracks = []  # type: list[STrack]
        self.removed_stracks = []  # type: list[STrack]

        self.frame_id = 0
        self.det_thresh = opt.conf_thres
        self.buffer_size = int(frame_rate / 30.0 * opt.track_buffer)
        self.max_time_lost = self.buffer_size
        self.max_per_image = opt.K

        self.kalman_filter = KalmanFilter()

        self.polygon = polygon
        self.paths = paths
        self.polygon2 = polygon2
        self.line2 = [self.polygon[1], self.polygon[2]]
        self.line1 = [self.polygon[4], self.polygon[3]] if len(
            self.polygon) == 5 else [self.polygon[0], self.polygon[3]] if len(
                self.polygon) == 4 else None
        self.two_polygon_system = False
        self.warmup_frame = 6 if self.two_polygon_system else 0
        self.virtual_polygon = [[0, 573], [0, 109], [1270, 109], [1270, 573]]

    def merge_outputs(self, detections):
        results = {}
        for j in range(1, self.opt.num_classes + 1):
            results[j] = np.concatenate(
                [detection[j] for detection in detections],
                axis=0).astype(np.float32)

        scores = np.hstack(
            [results[j][:, 4] for j in range(1, self.opt.num_classes + 1)])
        if len(scores) > self.max_per_image:
            kth = len(scores) - self.max_per_image
            thresh = np.partition(scores, kth)[kth]
            for j in range(1, self.opt.num_classes + 1):
                keep_inds = (results[j][:, 4] >= thresh)
                results[j] = results[j][keep_inds]
        return results

    def update(self, im_blob, img0):
        self.frame_id += 1
        activated_starcks = []
        refind_stracks = []
        lost_stracks = []
        removed_stracks = []

        width = img0.shape[1]
        height = img0.shape[0]
        init_polygon = self.polygon2 if self.two_polygon_system and self.frame_id >= self.warmup_frame else self.polygon
        two_wheel_polygon = init_polygon
        four_wheel_polygon = self.polygon
        virtual_polygon = self.virtual_polygon
        huge_box_thres = 230
        ''' Step 1: Network forward, get detections & embeddings'''
        with torch.no_grad():
            ori_imgs, framed_imgs, framed_metas = preprocess(
                [img0], max_size=self.input_size)
            device = torch.device('cuda:0')
            x = torch.stack(
                [torch.from_numpy(fi).to(device) for fi in framed_imgs], 0)
            x = x.to(torch.float32).permute(0, 3, 1, 2)
            features, regression, classification, anchors = self.detetection_model(
                x)
            regressBoxes = BBoxTransform()
            clipBoxes = ClipBoxes()
            out = postprocess(x, anchors, regression, classification,
                              regressBoxes, clipBoxes, self.opt.det_thres,
                              self.opt.nms_thres)
            out = invert_affine(framed_metas, out)
            bbox = []
            score = []
            types = []
            huge_vehicles = []
            for j in range(len(out[0]['rois'])):
                obj = self.obj_list[out[0]['class_ids'][j]]
                if obj in self.obj_interest:
                    x1, y1, x2, y2 = out[0]['rois'][j].astype(np.int)
                    #bike,bicycle
                    if (y1 + y2) / 2 > height / 2 and float(
                            out[0]['scores'][j]) <= 0.3:
                        continue
                    elif (y1 + y2) / 2 > 2 * height / 5 and float(
                            out[0]['scores']
                        [j]) <= 0.35 and obj not in self.person_or_motorcycle:
                        continue
                    if obj not in self.person_or_motorcycle and float(
                            out[0]['scores'][j]) >= 0.2:
                        bbox.append([x1, y1, x2, y2])
                        score.append(float(out[0]['scores'][j]))
                        types.append(obj)
                        huge_vehicles.append(False if (
                            y2 - y1) <= huge_box_thres else True)
                    elif obj in self.person_or_motorcycle:  #['bicycle',  'motorcycle']
                        bbox.append([x1, y1, x2, y2])
                        score.append(float(out[0]['scores'][j]))
                        types.append(obj)
                        huge_vehicles.append(False)
            # print(huge_vehicles)

        # vis
        # print(len(bbox))
        # print(img0.shape)
        # print(self.polygon)
        # for i in range(len(bbox)):
        #     bb = bbox[i]
        #     cv2.rectangle(img0, (bb[0], bb[1]),
        #                   (bb[2], bb[3]),
        #                   (0, 255, 0), 2)
        # cv2.polylines(img0,[np.asarray(self.polygon)],True,(0,255,255))
        # cv2.imshow('dets', img0)
        # cv2.waitKey(0)

        if len(bbox) > 0:
            '''Detections'''
            detections = [
                STrack(STrack.tlbr_to_tlwh(tlbr),
                       sco,
                       clas,
                       30,
                       huge_vehicle=hv)
                for (tlbr, sco, clas,
                     hv) in zip(bbox, score, types, huge_vehicles)
            ]

        else:
            detections = []

        detections_plot = detections.copy()
        ''' Add newly detected tracklets to tracked_stracks'''
        unconfirmed = []
        tracked_stracks = []  # type: list[STrack]
        for track in self.tracked_stracks:
            if not track.is_activated:
                unconfirmed.append(track)
            else:
                tracked_stracks.append(track)
        ''' Step 2: First association, with gating distance'''
        strack_pool, lost_map_tracks = joint_stracks(tracked_stracks,
                                                     self.lost_stracks)
        # Predict the current location with KF
        #for strack in strack_pool:
        #strack.predict()
        STrack.multi_predict(strack_pool)
        #dists = matching.embedding_distance(strack_pool, detections)
        detections = heuristic_occlusion_detection(detections)
        match_thres = 100
        dists = np.zeros(shape=(len(strack_pool), len(detections)))
        dists = matching.gate_cost_matrix(self.kalman_filter,
                                          dists,
                                          strack_pool,
                                          detections,
                                          type_diff=True)
        #dists = matching.fuse_motion(self.opt,self.kalman_filter, dists, strack_pool, detections,lost_map=lost_map_tracks,occlusion_map=occlusion_map,thres=match_thres)
        matches, u_track, u_detection = matching.linear_assignment(
            dists, thresh=match_thres)

        for itracked, idet in matches:
            track = strack_pool[itracked]
            det = detections[idet]
            if track.state == TrackState.Tracked:
                track.update(detections[idet], self.frame_id)
                activated_starcks.append(track)
            else:
                track.re_activate(det, self.frame_id, new_id=False)
                refind_stracks.append(track)
        ''' Step 3: Second association, with IOU'''
        detections = [detections[i] for i in u_detection]
        r_tracked_stracks = [
            strack_pool[i] for i in u_track
            if strack_pool[i].state == TrackState.Tracked
        ]
        dists = matching.iou_distance(r_tracked_stracks, detections)
        matches, u_track, u_detection = matching.linear_assignment(dists,
                                                                   thresh=0.5)

        for itracked, idet in matches:
            track = r_tracked_stracks[itracked]
            det = detections[idet]
            if track.state == TrackState.Tracked:
                track.update(det, self.frame_id)
                activated_starcks.append(track)
            else:
                track.re_activate(det, self.frame_id, new_id=False)
                refind_stracks.append(track)
        ''' '''
        for it in u_track:
            track = r_tracked_stracks[it]
            if not track.state == TrackState.Lost:
                track.mark_lost()
                lost_stracks.append(track)
        '''Deal with unconfirmed tracks, usually tracks with only one beginning frame'''
        detections = [detections[i] for i in u_detection]
        dists = matching.iou_distance(unconfirmed, detections)
        matches, u_unconfirmed, u_detection = matching.linear_assignment(
            dists, thresh=0.6)
        for itracked, idet in matches:
            unconfirmed[itracked].update(detections[idet], self.frame_id)
            activated_starcks.append(unconfirmed[itracked])
        for it in u_unconfirmed:
            track = unconfirmed[it]
            track.mark_removed()
            removed_stracks.append(track)
        """ Step 4: Init new stracks"""
        for inew in u_detection:
            track = detections[inew]
            track_init_polygon = init_polygon if not track.huge_vehicle else virtual_polygon
            if track.score < self.det_thresh or track.occlusion_status == True or check_bbox_outside_polygon(
                    track_init_polygon, track.tlbr):
                continue
            # track_types=self.person_or_motorcycle[0] if tlbrs_to_mean_area(track.track_trajectory) <=1500 else track.infer_type()
            if self.frame_id >= 5 and not check_bbox_inside_polygon(
                    track_init_polygon, track.tlbr
            ):  #and track_types in self.person_or_motorcycle #person, motorcycle
                continue
            track.activate(self.kalman_filter, self.frame_id)
            activated_starcks.append(track)
        """ Step 5: Update state and getting out of interest tracklet if have"""
        out_of_polygon_tracklet = []
        refind_stracks_copy = []
        activated_starcks_copy = []
        for idx, current_tracked_tracks in enumerate(
            [refind_stracks, activated_starcks]):  #

            for track in current_tracked_tracks:
                if tlbrs_to_mean_area(track.track_trajectory) <= 1000:
                    track_type = self.person_or_motorcycle[0]  #person
                else:
                    track_type = track.infer_type()
                if track_type in self.person_or_motorcycle:
                    out_polygon = two_wheel_polygon
                    p_type = 'two_wheel'
                else:
                    out_polygon = four_wheel_polygon  #if not track.huge_vehicle else virtual_polygon
                    p_type = 'four_wheel'
                if check_bbox_outside_polygon(out_polygon, track.tlbr):
                    track.mark_removed()
                    removed_stracks.append(track)
                    if (
                        (len(track.track_frames) >= 2 and self.frame_id <= 5)
                            or (len(track.track_frames) >= 5
                                and self.frame_id >= self.warmup_frame + 5)
                    ) and idx == 1:  ########## 4 is confident number of frame

                        track_center = [[(x[0] + x[2]) / 2, (x[1] + x[3]) / 2]
                                        for x in track.track_trajectory]
                        movement_id = counting_moi(
                            self.paths,
                            [(track_center[0], track_center[-1])])[0]
                        line_interest = self.line1 if str(
                            movement_id) == '1' else self.line2
                        out_direction = 'bottom' if str(
                            movement_id) == '1' else 'up'
                        frame_id = self.frame_id + kalman_predict_out_line(
                            track, line_interest, out_direction)
                        out_of_polygon_tracklet.append(
                            (frame_id, track.track_id, track_type,
                             movement_id))
                else:
                    refind_stracks_copy.append(
                        track) if idx == 0 else activated_starcks_copy.append(
                            track)
        refind_stracks = refind_stracks_copy
        activated_starcks = activated_starcks_copy

        lost_stracks_copy = []
        for track in lost_stracks:
            if tlbrs_to_mean_area(track.track_trajectory) <= 1000:
                track_type = self.person_or_motorcycle[0]  #person
            else:
                track_type = track.infer_type()
            if track_type in self.person_or_motorcycle:
                out_polygon = two_wheel_polygon
                p_type = 'two_wheel'
            else:
                out_polygon = four_wheel_polygon if not track.huge_vehicle else virtual_polygon
                p_type = 'four_wheel'

            if check_bbox_intersect_or_outside_polygon(out_polygon,
                                                       track.tlbr):
                track.mark_removed()
                removed_stracks.append(track)
                if ((len(track.track_frames) >= 2 and self.frame_id <= 5)
                        or (len(track.track_frames) >= 6
                            and self.frame_id >= self.warmup_frame + 5)):
                    track_center = [[(x[0] + x[2]) / 2, (x[1] + x[3]) / 2]
                                    for x in track.track_trajectory]
                    movement_id = counting_moi(
                        self.paths, [(track_center[0], track_center[-1])])[0]
                    line_interest = self.line1 if str(
                        movement_id) == '1' else self.line2
                    out_direction = 'bottom' if str(
                        movement_id) == '1' else 'up'
                    frame_id = self.frame_id + kalman_predict_out_line(
                        track, line_interest, out_direction)
                    out_of_polygon_tracklet.append(
                        (frame_id, track.track_id, track_type, movement_id))
            else:
                lost_stracks_copy.append(track)

        lost_stracks = lost_stracks_copy

        for track in self.lost_stracks:
            if self.frame_id - track.end_frame > self.max_time_lost:
                track.mark_removed()
                removed_stracks.append(track)
            #Remove out of screen tracklet
            elif track.tlwh[0] + track.tlwh[2] // 2 > width or track.tlwh[
                    1] + track.tlwh[3] // 2 > height or min(
                        track.tlwh[0] + track.tlwh[2] // 2,
                        track.tlwh[1] + track.tlwh[3] // 2) < 0:
                track.num_out_frame += 1
                if track.num_out_frame > STrack.out_of_frame_patience:
                    track.mark_removed()
                    removed_stracks.append(track)

        # print('Ramained match {} s'.format(t4-t3))
        # print(out_of_polygon_tracklet)
        self.tracked_stracks = [
            t for t in self.tracked_stracks if t.state == TrackState.Tracked
        ]
        self.tracked_stracks, _ = joint_stracks(self.tracked_stracks,
                                                activated_starcks)
        self.tracked_stracks, _ = joint_stracks(self.tracked_stracks,
                                                refind_stracks)
        self.lost_stracks = sub_stracks(self.lost_stracks,
                                        self.tracked_stracks)
        self.lost_stracks.extend(lost_stracks)
        self.lost_stracks = sub_stracks(self.lost_stracks,
                                        self.removed_stracks)
        self.removed_stracks.extend(removed_stracks)
        self.tracked_stracks, self.lost_stracks = remove_duplicate_stracks(
            self.tracked_stracks, self.lost_stracks)
        #self.merge_track()
        output_stracks = [
            track for track in self.tracked_stracks if track.is_activated
        ]

        # logger.debug('===========Frame {}=========='.format(self.frame_id))
        # logger.debug('Activated: {}'.format([track.track_id for track in activated_starcks]))
        # logger.debug('Refind: {}'.format([track.track_id for track in refind_stracks]))
        # logger.debug('Lost: {}'.format([track.track_id for track in lost_stracks]))
        # logger.debug('Removed: {}'.format([track.track_id for track in removed_stracks]))

        return output_stracks, detections_plot, out_of_polygon_tracklet

    #can paralel,current bottleneck of model
    def merge_track(self,
                    min_thres=0.2,
                    distance_thres=15,
                    consitence_thres=10):
        def is_overlap(lost_track, tracked_track):
            if tracked_track.start_frame > lost_track.end_frame or lost_track.start_frame > tracked_track.end_frame:
                return False

        def predict_future(lost_track, num_frame):
            mean, cov = lost_track.mean, lost_track.covariance
            for _ in range(num_frame):
                mean, cov = lost_track.kalman_filter.predict(mean, cov)
            return mean, cov

        def cluster_compare(lost_track, tracked_track):
            return np.min(
                cdist(lost_track.cluster_features['centers'],
                      tracked_track.cluster_features['centers'],
                      metric='cosine'))

        def distance(lost_track,
                     tracked_track,
                     min_thres=min_thres,
                     distance_thres=distance_thres):
            if is_overlap(lost_track, tracked_track):
                return np.inf
            else:
                pred_mean, pred_cov = predict_future(
                    lost_track,
                    tracked_track.start_frame - lost_track.end_frame)

                tracked_xyah = STrack.tlwh_to_xyah(tracked_track._tlwh)
                if self.kalman_filter.gating_distance(
                        pred_mean, pred_cov, tracked_xyah) > distance_thres:
                    return np.inf
                else:
                    return cluster_compare(lost_track, tracked_track)

        cost_matrix = np.zeros(shape=(len(self.lost_stracks),
                                      len(self.tracked_stracks)))
        for i in range(cost_matrix.shape[0]):
            for j in range(cost_matrix.shape[1]):
                if min(len(self.lost_stracks[i].track_frames),
                       len(self.tracked_stracks[j].track_frames)
                       ) <= consitence_thres:
                    cost_matrix[i][j] = np.inf
                else:
                    cost_matrix[i][j] = distance(self.lost_stracks[i],
                                                 self.tracked_stracks[j])

        matches, _, _ = matching.linear_assignment(cost_matrix,
                                                   thresh=min_thres)
        map_lost_track = np.ones_like(self.lost_stracks, dtype=np.int)

        for i in range(cost_matrix.shape[0]):
            for j in range(cost_matrix.shape[1]):
                if cost_matrix[i][j] <= 1:
                    print('sim of ' + str(self.lost_stracks[i].track_id) +
                          ' and ' + str(self.tracked_stracks[j].track_id) +
                          ' : ' + str(cost_matrix[i][j]))
        if len(matches) == 0:
            return

        for ilost_track, i_tracked_track in matches:
            print('------------------------------------')
            print('merge ' +
                  str(self.tracked_stracks[i_tracked_track].track_id) +
                  ' to ' + str(self.lost_stracks[ilost_track].track_id))
            map_lost_track[ilost_track] = 0  # pylint: disable=unsupported-assignment-operation
            for num_clus in range(
                    len(self.tracked_stracks[i_tracked_track].
                        cluster_features['cluster'])):
                for clus in self.tracked_stracks[
                        i_tracked_track].cluster_features['cluster'][num_clus]:
                    self.lost_stracks[ilost_track].update_cluster(clus)
            self.lost_stracks[ilost_track].mean, self.lost_stracks[
                ilost_track].covariance = self.tracked_stracks[
                    i_tracked_track].mean, self.tracked_stracks[
                        i_tracked_track].covariance
            self.lost_stracks[
                ilost_track].track_frames += self.tracked_stracks[
                    i_tracked_track].track_frames
            self.lost_stracks[ilost_track].frame_id = self.tracked_stracks[
                i_tracked_track].frame_id
            self.tracked_stracks[i_tracked_track] = self.lost_stracks[
                ilost_track]

        new_lost_tracks = []
        for ilost_track in range(len(map_lost_track)):
            if map_lost_track[ilost_track] == 1:
                new_lost_tracks.append(self.lost_stracks[ilost_track])
        self.lost_stracks = new_lost_tracks