Spaces:
Runtime error
Runtime error
| # -------------------------------------------------------- | |
| # Python Single Object Tracking Evaluation | |
| # Licensed under The MIT License [see LICENSE for details] | |
| # Written by Fangyi Zhang | |
| # @author fangyi.zhang@vipl.ict.ac.cn | |
| # @project https://github.com/StrangerZhang/pysot-toolkit.git | |
| # Revised for SiamMask by foolwood | |
| # -------------------------------------------------------- | |
| import numpy as np | |
| from ..utils import calculate_failures, calculate_accuracy, calculate_expected_overlap | |
| class EAOBenchmark: | |
| """ | |
| Args: | |
| dataset: | |
| """ | |
| def __init__(self, dataset, skipping=5, tags=['all']): | |
| self.dataset = dataset | |
| self.skipping = skipping | |
| self.tags = tags | |
| # NOTE we not use gmm to generate low, high, peak value | |
| if dataset.name in ['VOT2019']: | |
| self.low = 46 | |
| self.high = 291 | |
| self.peak = 128 | |
| elif dataset.name in ['VOT2018', 'VOT2017']: | |
| self.low = 100 | |
| self.high = 356 | |
| self.peak = 160 | |
| elif dataset.name == 'VOT2016': | |
| self.low = 100 # TODO | |
| self.high = 356 | |
| self.peak = 160 | |
| def eval(self, eval_trackers=None): | |
| """ | |
| Args: | |
| eval_tags: list of tag | |
| eval_trackers: list of tracker name | |
| Returns: | |
| eao: dict of results | |
| """ | |
| if eval_trackers is None: | |
| eval_trackers = self.dataset.tracker_names | |
| if isinstance(eval_trackers, str): | |
| eval_trackers = [eval_trackers] | |
| ret = {} | |
| for tracker_name in eval_trackers: | |
| eao = self._calculate_eao(tracker_name, self.tags) | |
| ret[tracker_name] = eao | |
| return ret | |
| def show_result(self, result, topk=10): | |
| """pretty print result | |
| Args: | |
| result: returned dict from function eval | |
| """ | |
| if len(self.tags) == 1: | |
| tracker_name_len = max((max([len(x) for x in result.keys()])+2), 12) | |
| header = ("|{:^"+str(tracker_name_len)+"}|{:^10}|").format('Tracker Name', 'EAO') | |
| bar = '-'*len(header) | |
| formatter = "|{:^20}|{:^10.3f}|" | |
| print(bar) | |
| print(header) | |
| print(bar) | |
| tracker_eao = sorted(result.items(), | |
| key=lambda x: x[1]['all'], | |
| reverse=True)[:topk] | |
| for tracker_name, eao in tracker_eao: | |
| print(formatter.format(tracker_name, eao)) | |
| print(bar) | |
| else: | |
| header = "|{:^20}|".format('Tracker Name') | |
| header += "{:^7}|{:^15}|{:^14}|{:^15}|{:^13}|{:^11}|{:^7}|".format(*self.tags) | |
| bar = '-'*len(header) | |
| formatter = "{:^7.3f}|{:^15.3f}|{:^14.3f}|{:^15.3f}|{:^13.3f}|{:^11.3f}|{:^7.3f}|" | |
| print(bar) | |
| print(header) | |
| print(bar) | |
| sorted_tacker = sorted(result.items(), | |
| key=lambda x: x[1]['all'], | |
| reverse=True)[:topk] | |
| sorted_tacker = [x[0] for x in sorted_tacker] | |
| for tracker_name in sorted_tacker: | |
| print("|{:^20}|".format(tracker_name)+formatter.format( | |
| *[result[tracker_name][x] for x in self.tags])) | |
| print(bar) | |
| def _calculate_eao(self, tracker_name, tags): | |
| all_overlaps = [] | |
| all_failures = [] | |
| video_names = [] | |
| gt_traj_length = [] | |
| for video in self.dataset: | |
| gt_traj = video.gt_traj | |
| if tracker_name not in video.pred_trajs: | |
| tracker_trajs = video.load_tracker(self.dataset.tracker_path, tracker_name, False) | |
| else: | |
| tracker_trajs = video.pred_trajs[tracker_name] | |
| for tracker_traj in tracker_trajs: | |
| gt_traj_length.append(len(gt_traj)) | |
| video_names.append(video.name) | |
| overlaps = calculate_accuracy(tracker_traj, gt_traj, bound=(video.width-1, video.height-1))[1] | |
| failures = calculate_failures(tracker_traj)[1] | |
| all_overlaps.append(overlaps) | |
| all_failures.append(failures) | |
| fragment_num = sum([len(x)+1 for x in all_failures]) | |
| max_len = max([len(x) for x in all_overlaps]) | |
| seq_weight = 1 / len(tracker_trajs) | |
| eao = {} | |
| for tag in tags: | |
| # prepare segments | |
| fweights = np.ones((fragment_num)) * np.nan | |
| fragments = np.ones((fragment_num, max_len)) * np.nan | |
| seg_counter = 0 | |
| for name, traj_len, failures, overlaps in zip(video_names, gt_traj_length, | |
| all_failures, all_overlaps): | |
| if len(failures) > 0: | |
| points = [x+self.skipping for x in failures if | |
| x+self.skipping <= len(overlaps)] | |
| points.insert(0, 0) | |
| for i in range(len(points)): | |
| if i != len(points) - 1: | |
| fragment = np.array(overlaps[points[i]:points[i+1]+1]) | |
| fragments[seg_counter, :] = 0 | |
| else: | |
| fragment = np.array(overlaps[points[i]:]) | |
| fragment[np.isnan(fragment)] = 0 | |
| fragments[seg_counter, :len(fragment)] = fragment | |
| if i != len(points) - 1: | |
| tag_value = self.dataset[name].select_tag(tag, points[i], points[i+1]+1) | |
| w = sum(tag_value) / (points[i+1] - points[i]+1) | |
| fweights[seg_counter] = seq_weight * w | |
| else: | |
| tag_value = self.dataset[name].select_tag(tag, points[i], len(overlaps)) | |
| w = sum(tag_value) / (traj_len - points[i]+1e-16) | |
| fweights[seg_counter] = seq_weight * w | |
| seg_counter += 1 | |
| else: | |
| # no failure | |
| max_idx = min(len(overlaps), max_len) | |
| fragments[seg_counter, :max_idx] = overlaps[:max_idx] | |
| tag_value = self.dataset[name].select_tag(tag, 0, max_idx) | |
| w = sum(tag_value) / max_idx | |
| fweights[seg_counter] = seq_weight * w | |
| seg_counter += 1 | |
| expected_overlaps = calculate_expected_overlap(fragments, fweights) | |
| # caculate eao | |
| weight = np.zeros((len(expected_overlaps))) | |
| weight[self.low-1:self.high-1+1] = 1 | |
| is_valid = np.logical_not(np.isnan(expected_overlaps)) | |
| eao_ = np.sum(expected_overlaps[is_valid] * weight[is_valid]) / np.sum(weight[is_valid]) | |
| eao[tag] = eao_ | |
| return eao | |