From 2b09e33188461d28bf1bbdfc5553dad296998972 Mon Sep 17 00:00:00 2001 From: huanglianghua Date: Tue, 4 Dec 2018 16:00:01 +0800 Subject: [PATCH] add dtb70 and tcolor128 interfaces --- README.md | 4 +- got10k/datasets/__init__.py | 2 + got10k/datasets/dtb70.py | 68 +++++++++++++++++++++++ got10k/datasets/tcolor128.py | 98 +++++++++++++++++++++++++++++++++ got10k/experiments/__init__.py | 2 + got10k/experiments/dtb70.py | 27 +++++++++ got10k/experiments/otb.py | 3 +- got10k/experiments/tcolor128.py | 27 +++++++++ got10k/experiments/vot.py | 3 +- tests/test_datasets.py | 12 +++- tests/test_experiments.py | 18 +++++- 11 files changed, 259 insertions(+), 5 deletions(-) create mode 100644 got10k/datasets/dtb70.py create mode 100644 got10k/datasets/tcolor128.py create mode 100644 got10k/experiments/dtb70.py create mode 100644 got10k/experiments/tcolor128.py diff --git a/README.md b/README.md index 4932f00..86fbfa5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # GOT-10k Python Toolkit -This repository contains the official python toolkit for running experiments and evaluate performance on [GOT-10k](https://got-10k.github.io) benchmark. For convenience, it also provides unofficial implementation of tracking pipelines for [OTB](http://cvlab.hanyang.ac.kr/tracker_benchmark/index.html) and [VOT](http://votchallenge.net) benchmarks. The code is written in pure python and is compile-free. Although we support both python2 and python3, we recommend python3 for better performance. +This repository contains the official python toolkit for running experiments and evaluate performance on [GOT-10k](https://got-10k.github.io) benchmark. The code is written in pure python and is compile-free. Although we support both python2 and python3, we recommend python3 for better performance. + +For convenience, the toolkit also provides unofficial implementation of dataset interfaces and tracking pipelines for [OTB](http://cvlab.hanyang.ac.kr/tracker_benchmark/index.html), [VOT](http://votchallenge.net), [DTB70](https://github.com/flyers/drone-tracking) and [TColor128](http://www.dabi.temple.edu/~hbling/data/TColor-128/TColor-128.html) benchmarks. [GOT-10k](https://got-10k.github.io) is a large, high-diversity and one-shot database for evaluating generic purposed visual trackers. If you use the GOT-10k database or toolkits for a research publication, please consider citing: diff --git a/got10k/datasets/__init__.py b/got10k/datasets/__init__.py index 50ed3b8..e8e237b 100644 --- a/got10k/datasets/__init__.py +++ b/got10k/datasets/__init__.py @@ -3,4 +3,6 @@ from .got10k import GOT10k from .otb import OTB from .vot import VOT +from .dtb70 import DTB70 +from .tcolor128 import TColor128 from .vid import ImageNetVID diff --git a/got10k/datasets/dtb70.py b/got10k/datasets/dtb70.py new file mode 100644 index 0000000..1ce459d --- /dev/null +++ b/got10k/datasets/dtb70.py @@ -0,0 +1,68 @@ +from __future__ import absolute_import, print_function + +import os +import glob +import numpy as np +import six + + +class DTB70(object): + """`DTB70 `_ Dataset. + + Publication: + ``Visual object tracking for unmanned aerial vehicles: A benchmark and new motion models``, + Y. Wu, J. Lim and M.-H. Yang, IEEE TPAMI 2015. + + Args: + root_dir (string): Root directory of dataset where sequence + folders exist. + """ + def __init__(self, root_dir): + super(DTB70, self).__init__() + self.root_dir = root_dir + self._check_integrity(root_dir) + + self.anno_files = sorted(glob.glob( + os.path.join(root_dir, '*/groundtruth_rect.txt'))) + self.seq_dirs = [os.path.dirname(f) for f in self.anno_files] + self.seq_names = [os.path.basename(d) for d in self.seq_dirs] + + def __getitem__(self, index): + r""" + Args: + index (integer or string): Index or name of a sequence. + + Returns: + tuple: (img_files, anno), where ``img_files`` is a list of + file names and ``anno`` is a N x 4 (rectangles) numpy array. + """ + if isinstance(index, six.string_types): + if not index in self.seq_names: + raise Exception('Sequence {} not found.'.format(index)) + index = self.seq_names.index(index) + + img_files = sorted(glob.glob( + os.path.join(self.seq_dirs[index], 'img/*.jpg'))) + anno = np.loadtxt(self.anno_files[index], delimiter=',') + assert len(img_files) == len(anno) + assert anno.shape[1] == 4 + + return img_files, anno + + def __len__(self): + return len(self.seq_names) + + def _check_integrity(self, root_dir): + seq_names = os.listdir(root_dir) + seq_names = [n for n in seq_names if not n[0] == '.'] + + if os.path.isdir(root_dir) and len(seq_names) > 0: + # check each sequence folder + for seq_name in seq_names: + seq_dir = os.path.join(root_dir, seq_name) + if not os.path.isdir(seq_dir): + print('Warning: sequence %s not exist.' % seq_name) + else: + # dataset not exist + raise Exception('Dataset not found or corrupted. ' + + 'You can use download=True to download it.') diff --git a/got10k/datasets/tcolor128.py b/got10k/datasets/tcolor128.py new file mode 100644 index 0000000..cd45970 --- /dev/null +++ b/got10k/datasets/tcolor128.py @@ -0,0 +1,98 @@ +from __future__ import absolute_import, print_function + +import os +import glob +import numpy as np +import six + +from ..utils.ioutils import download, extract + + +class TColor128(object): + """`TColor128 `_ Dataset. + + Publication: + ``Encoding color information for visual tracking: algorithms and benchmark``, + P. Liang, E. Blasch and H. Ling, TIP, 2015. + + Args: + root_dir (string): Root directory of dataset where sequence + folders exist. + """ + def __init__(self, root_dir, download=True): + super(TColor128, self).__init__() + self.root_dir = root_dir + if download: + self._download(root_dir) + self._check_integrity(root_dir) + + self.anno_files = sorted(glob.glob( + os.path.join(root_dir, '*/*_gt.txt'))) + self.seq_dirs = [os.path.dirname(f) for f in self.anno_files] + self.seq_names = [os.path.basename(d) for d in self.seq_dirs] + # valid frame range for each sequence + self.range_files = [os.path.join( + root_dir, '%s/%s_frames.txt' % (n, n)) + for n in self.seq_names] + + def __getitem__(self, index): + r""" + Args: + index (integer or string): Index or name of a sequence. + + Returns: + tuple: (img_files, anno), where ``img_files`` is a list of + file names and ``anno`` is a N x 4 (rectangles) numpy array. + """ + if isinstance(index, six.string_types): + if not index in self.seq_names: + raise Exception('Sequence {} not found.'.format(index)) + index = self.seq_names.index(index) + + # load valid frame range + frames = np.loadtxt( + self.range_files[index], dtype=int, delimiter=',') + img_files = [os.path.join( + self.seq_dirs[index], 'img/%04d.jpg' % f) + for f in range(frames[0], frames[1] + 1)] + + # load annotations + anno = np.loadtxt(self.anno_files[index], delimiter=',') + assert len(img_files) == len(anno) + assert anno.shape[1] == 4 + + return img_files, anno + + def __len__(self): + return len(self.seq_names) + + def _download(self, root_dir): + if not os.path.isdir(root_dir): + os.makedirs(root_dir) + elif len(os.listdir(root_dir)) > 100: + print('Files already downloaded.') + return + + url = 'http://www.dabi.temple.edu/~hbling/data/TColor-128/Temple-color-128.zip' + zip_file = os.path.join(root_dir, 'Temple-color-128.zip') + print('Downloading to %s...' % zip_file) + download(url, zip_file) + print('\nExtracting to %s...' % root_dir) + extract(zip_file, root_dir) + + return root_dir + + def _check_integrity(self, root_dir): + seq_names = os.listdir(root_dir) + seq_names = [n for n in seq_names if not n[0] == '.'] + + if os.path.isdir(root_dir) and len(seq_names) > 0: + # check each sequence folder + for seq_name in seq_names: + seq_dir = os.path.join(root_dir, seq_name) + if not os.path.isdir(seq_dir): + print('Warning: sequence %s not exist.' % seq_name) + else: + # dataset not exist + raise Exception('Dataset not found or corrupted. ' + + 'You can use download=True to download it.') diff --git a/got10k/experiments/__init__.py b/got10k/experiments/__init__.py index 4208e61..b3a14c5 100644 --- a/got10k/experiments/__init__.py +++ b/got10k/experiments/__init__.py @@ -3,3 +3,5 @@ from .got10k import ExperimentGOT10k from .otb import ExperimentOTB from .vot import ExperimentVOT +from .dtb70 import ExperimentDTB70 +from .tcolor128 import ExperimentTColor128 diff --git a/got10k/experiments/dtb70.py b/got10k/experiments/dtb70.py new file mode 100644 index 0000000..27e8444 --- /dev/null +++ b/got10k/experiments/dtb70.py @@ -0,0 +1,27 @@ +from __future__ import absolute_import + +import os + +from .otb import ExperimentOTB +from ..datasets import DTB70 + + +class ExperimentDTB70(ExperimentOTB): + r"""Experiment pipeline and evaluation toolkit for DTB70 dataset. + + Args: + root_dir (string): Root directory of DTB70 dataset. + result_dir (string, optional): Directory for storing tracking + results. Default is ``./results``. + report_dir (string, optional): Directory for storing performance + evaluation results. Default is ``./reports``. + """ + def __init__(self, root_dir, + result_dir='results', report_dir='reports'): + self.dataset = DTB70(root_dir) + self.result_dir = os.path.join(result_dir, 'DTB70') + self.report_dir = os.path.join(report_dir, 'DTB70') + # as nbins_iou increases, the success score + # converges to the average overlap (AO) + self.nbins_iou = 21 + self.nbins_ce = 51 diff --git a/got10k/experiments/otb.py b/got10k/experiments/otb.py index f054747..a9d3697 100644 --- a/got10k/experiments/otb.py +++ b/got10k/experiments/otb.py @@ -35,7 +35,8 @@ def __init__(self, root_dir, version=2015, self.nbins_ce = 51 def run(self, tracker, visualize=False): - print('Running tracker %s on OTB...' % tracker.name) + print('Running tracker %s on %s...' % ( + tracker.name, type(self.dataset).__name__)) # loop over the complete dataset for s, (img_files, anno) in enumerate(self.dataset): diff --git a/got10k/experiments/tcolor128.py b/got10k/experiments/tcolor128.py new file mode 100644 index 0000000..e21239f --- /dev/null +++ b/got10k/experiments/tcolor128.py @@ -0,0 +1,27 @@ +from __future__ import absolute_import + +import os + +from .otb import ExperimentOTB +from ..datasets import TColor128 + + +class ExperimentTColor128(ExperimentOTB): + r"""Experiment pipeline and evaluation toolkit for TColor128 dataset. + + Args: + root_dir (string): Root directory of TColor128 dataset. + result_dir (string, optional): Directory for storing tracking + results. Default is ``./results``. + report_dir (string, optional): Directory for storing performance + evaluation results. Default is ``./reports``. + """ + def __init__(self, root_dir, + result_dir='results', report_dir='reports'): + self.dataset = TColor128(root_dir) + self.result_dir = os.path.join(result_dir, 'TColor128') + self.report_dir = os.path.join(report_dir, 'TColor128') + # as nbins_iou increases, the success score + # converges to the average overlap (AO) + self.nbins_iou = 21 + self.nbins_ce = 51 diff --git a/got10k/experiments/vot.py b/got10k/experiments/vot.py index c2f70aa..c0d9b7f 100644 --- a/got10k/experiments/vot.py +++ b/got10k/experiments/vot.py @@ -60,7 +60,8 @@ def __init__(self, root_dir, version=2017, 'size_change', 'motion_change', 'empty'] def run(self, tracker, visualize=False): - print('Running tracker %s on VOT...' % tracker.name) + print('Running tracker %s on %s...' % ( + tracker.name, type(self.dataset).__name__)) # run all specified experiments if 'supervised' in self.experiments: diff --git a/tests/test_datasets.py b/tests/test_datasets.py index e7c45aa..ae9067e 100644 --- a/tests/test_datasets.py +++ b/tests/test_datasets.py @@ -4,7 +4,7 @@ import os import random -from got10k.datasets import GOT10k, OTB, VOT, ImageNetVID +from got10k.datasets import GOT10k, OTB, VOT, DTB70, TColor128, ImageNetVID class TestDatasets(unittest.TestCase): @@ -38,6 +38,16 @@ def test_vot(self): dataset = VOT(root_dir, anno_type='rect', return_meta=True) self._check_dataset(dataset) + def test_dtb70(self): + root_dir = os.path.join(self.data_dir, 'DTB70') + dataset = DTB70(root_dir) + self._check_dataset(dataset) + + def test_tcolor128(self): + root_dir = os.path.join(self.data_dir, 'Temple-color-128') + dataset = TColor128(root_dir) + self._check_dataset(dataset) + def test_vid(self): root_dir = os.path.join(self.data_dir, 'ILSVRC') dataset = ImageNetVID(root_dir, subset=('train', 'val')) diff --git a/tests/test_experiments.py b/tests/test_experiments.py index 26e6d3e..92e5c0f 100644 --- a/tests/test_experiments.py +++ b/tests/test_experiments.py @@ -5,7 +5,7 @@ from got10k.trackers import IdentityTracker from got10k.experiments import ExperimentGOT10k, ExperimentOTB, \ - ExperimentVOT + ExperimentVOT, ExperimentDTB70, ExperimentTColor128 class TestExperiments(unittest.TestCase): @@ -41,6 +41,22 @@ def test_vot(self): # report performance experiment.report([self.tracker.name]) + def test_dtb70(self): + root_dir = os.path.join(self.data_dir, 'DTB70') + # run experiment + experiment = ExperimentDTB70(root_dir) + experiment.run(self.tracker, visualize=False) + # report performance + experiment.report([self.tracker.name]) + + def test_tcolor128(self): + root_dir = os.path.join(self.data_dir, 'Temple-color-128') + # run experiment + experiment = ExperimentTColor128(root_dir) + experiment.run(self.tracker, visualize=False) + # report performance + experiment.report([self.tracker.name]) + if __name__ == '__main__': unittest.main()