Yuantao Feng
commited on
Commit
·
0199e9f
1
Parent(s):
18103a9
Decoupling dataloader and benchmark runner (#16)
Browse files* impl dataloader factory
* set a type to init all instances for benchmarks
- benchmark/benchmark.py +35 -58
- benchmark/config/face_detection_yunet.yaml +2 -2
- benchmark/config/face_recognition_sface.yaml +1 -2
- benchmark/config/human_segmentation_pphumanseg.yaml +2 -2
- benchmark/config/image_classification_ppresnet.yaml +2 -2
- benchmark/config/qrcode_wechatqrcode.yaml +2 -2
- benchmark/config/text_detection_db.yaml +2 -2
- benchmark/config/text_recognition_crnn.yaml +1 -2
- benchmark/utils/__init__.py +1 -0
- benchmark/utils/dataloaders/__init__.py +6 -0
- benchmark/utils/dataloaders/base.py +12 -0
- benchmark/utils/dataloaders/base_dataloader.py +67 -0
- benchmark/utils/dataloaders/classification.py +42 -0
- benchmark/utils/dataloaders/recognition.py +30 -0
- benchmark/utils/dataloaders/tracking.py +25 -0
- benchmark/utils/factory.py +8 -1
- benchmark/utils/metrics/base.py +9 -14
- benchmark/utils/metrics/base_metric.py +0 -3
- benchmark/utils/metrics/detection.py +14 -18
- benchmark/utils/metrics/recognition.py +1 -6
benchmark/benchmark.py
CHANGED
|
@@ -7,17 +7,23 @@ import cv2 as cv
|
|
| 7 |
|
| 8 |
# from ..models import MODELS
|
| 9 |
from models import MODELS
|
| 10 |
-
from utils import METRICS
|
| 11 |
|
| 12 |
parser = argparse.ArgumentParser("Benchmarks for OpenCV Zoo.")
|
| 13 |
parser.add_argument('--cfg', '-c', type=str,
|
| 14 |
help='Benchmarking on the given config.')
|
| 15 |
args = parser.parse_args()
|
| 16 |
|
| 17 |
-
def build_from_cfg(cfg, registery, key=
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
def prepend_pythonpath(cfg):
|
| 23 |
for k, v in cfg.items():
|
|
@@ -27,62 +33,26 @@ def prepend_pythonpath(cfg):
|
|
| 27 |
if 'path' in k.lower():
|
| 28 |
cfg[k] = os.path.join(os.environ['PYTHONPATH'], v)
|
| 29 |
|
| 30 |
-
class Data:
|
| 31 |
-
def __init__(self, **kwargs):
|
| 32 |
-
self._path = kwargs.pop('path', None)
|
| 33 |
-
assert self._path, 'Benchmark[\'data\'][\'path\'] cannot be empty.'
|
| 34 |
-
|
| 35 |
-
self._files = kwargs.pop('files', None)
|
| 36 |
-
if not self._files:
|
| 37 |
-
print('Benchmark[\'data\'][\'files\'] is empty, loading all images by default.')
|
| 38 |
-
self._files = list()
|
| 39 |
-
for filename in os.listdir(self._path):
|
| 40 |
-
if filename.endswith('jpg') or filename.endswith('png'):
|
| 41 |
-
self._files.append(filename)
|
| 42 |
-
|
| 43 |
-
self._use_label = kwargs.pop('useLabel', False)
|
| 44 |
-
if self._use_label:
|
| 45 |
-
self._labels = self._load_label()
|
| 46 |
-
|
| 47 |
-
self._to_rgb = kwargs.pop('toRGB', False)
|
| 48 |
-
self._resize = tuple(kwargs.pop('resize', []))
|
| 49 |
-
self._center_crop = kwargs.pop('centerCrop', None)
|
| 50 |
-
|
| 51 |
-
def _load_label(self):
|
| 52 |
-
labels = dict.fromkeys(self._files, None)
|
| 53 |
-
for filename in self._files:
|
| 54 |
-
labels[filename] = np.loadtxt(os.path.join(self._path, '{}.txt'.format(filename[:-4])), ndmin=2)
|
| 55 |
-
return labels
|
| 56 |
-
|
| 57 |
-
def __getitem__(self, idx):
|
| 58 |
-
image = cv.imread(os.path.join(self._path, self._files[idx]))
|
| 59 |
-
|
| 60 |
-
if self._to_rgb:
|
| 61 |
-
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
|
| 62 |
-
if self._resize:
|
| 63 |
-
image = cv.resize(image, self._resize)
|
| 64 |
-
if self._center_crop:
|
| 65 |
-
h, w, _ = image.shape
|
| 66 |
-
w_crop = int((w - self._center_crop) / 2.)
|
| 67 |
-
assert w_crop >= 0
|
| 68 |
-
h_crop = int((h - self._center_crop) / 2.)
|
| 69 |
-
assert h_crop >= 0
|
| 70 |
-
image = image[w_crop:w-w_crop, h_crop:h-h_crop, :]
|
| 71 |
-
|
| 72 |
-
if self._use_label:
|
| 73 |
-
return self._files[idx], image, self._labels[self._files[idx]]
|
| 74 |
-
else:
|
| 75 |
-
return self._files[idx], image
|
| 76 |
-
|
| 77 |
class Benchmark:
|
| 78 |
def __init__(self, **kwargs):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
self._data_dict = kwargs.pop('data', None)
|
| 80 |
assert self._data_dict, 'Benchmark[\'data\'] cannot be empty and must have path and files.'
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
| 82 |
|
| 83 |
self._metric_dict = kwargs.pop('metric', None)
|
| 84 |
-
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
backend_id = kwargs.pop('backend', 'default')
|
| 88 |
available_backends = dict(
|
|
@@ -115,8 +85,15 @@ class Benchmark:
|
|
| 115 |
model.setBackend(self._backend)
|
| 116 |
model.setTarget(self._target)
|
| 117 |
|
| 118 |
-
|
| 119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
def printResults(self):
|
| 122 |
for imgName, results in self._benchmark_results.items():
|
|
@@ -138,7 +115,7 @@ if __name__ == '__main__':
|
|
| 138 |
benchmark = Benchmark(**cfg['Benchmark'])
|
| 139 |
|
| 140 |
# Instantiate model
|
| 141 |
-
model = build_from_cfg(cfg=cfg['Model'], registery=MODELS)
|
| 142 |
|
| 143 |
# Run benchmarking
|
| 144 |
print('Benchmarking {}:'.format(model.name))
|
|
|
|
| 7 |
|
| 8 |
# from ..models import MODELS
|
| 9 |
from models import MODELS
|
| 10 |
+
from utils import METRICS, DATALOADERS
|
| 11 |
|
| 12 |
parser = argparse.ArgumentParser("Benchmarks for OpenCV Zoo.")
|
| 13 |
parser.add_argument('--cfg', '-c', type=str,
|
| 14 |
help='Benchmarking on the given config.')
|
| 15 |
args = parser.parse_args()
|
| 16 |
|
| 17 |
+
def build_from_cfg(cfg, registery, key=None, name=None):
|
| 18 |
+
if key is not None:
|
| 19 |
+
obj_name = cfg.pop(key)
|
| 20 |
+
obj = registery.get(obj_name)
|
| 21 |
+
return obj(**cfg)
|
| 22 |
+
elif name is not None:
|
| 23 |
+
obj = registery.get(name)
|
| 24 |
+
return obj(**cfg)
|
| 25 |
+
else:
|
| 26 |
+
raise NotImplementedError()
|
| 27 |
|
| 28 |
def prepend_pythonpath(cfg):
|
| 29 |
for k, v in cfg.items():
|
|
|
|
| 33 |
if 'path' in k.lower():
|
| 34 |
cfg[k] = os.path.join(os.environ['PYTHONPATH'], v)
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
class Benchmark:
|
| 37 |
def __init__(self, **kwargs):
|
| 38 |
+
self._type = kwargs.pop('type', None)
|
| 39 |
+
if self._type is None:
|
| 40 |
+
self._type = 'Base'
|
| 41 |
+
print('Benchmark[\'type\'] is omitted, set to \'Base\' by default.')
|
| 42 |
+
|
| 43 |
self._data_dict = kwargs.pop('data', None)
|
| 44 |
assert self._data_dict, 'Benchmark[\'data\'] cannot be empty and must have path and files.'
|
| 45 |
+
if 'type' in self._data_dict:
|
| 46 |
+
self._dataloader = build_from_cfg(self._data_dict, registery=DATALOADERS, key='type')
|
| 47 |
+
else:
|
| 48 |
+
self._dataloader = build_from_cfg(self._data_dict, registery=DATALOADERS, name=self._type)
|
| 49 |
|
| 50 |
self._metric_dict = kwargs.pop('metric', None)
|
| 51 |
+
assert self._metric_dict, 'Benchmark[\'metric\'] cannot be empty.'
|
| 52 |
+
if 'type' in self._metric_dict:
|
| 53 |
+
self._metric = build_from_cfg(self._metric_dict, registery=METRICS, key='type')
|
| 54 |
+
else:
|
| 55 |
+
self._metric = build_from_cfg(self._metric_dict, registery=METRICS, name=self._type)
|
| 56 |
|
| 57 |
backend_id = kwargs.pop('backend', 'default')
|
| 58 |
available_backends = dict(
|
|
|
|
| 85 |
model.setBackend(self._backend)
|
| 86 |
model.setTarget(self._target)
|
| 87 |
|
| 88 |
+
if 'video' in self._dataloader.name.lower():
|
| 89 |
+
model.init(self._dataloader.getROI())
|
| 90 |
+
|
| 91 |
+
for data in self._dataloader:
|
| 92 |
+
filename, img = data[:2]
|
| 93 |
+
size = [img.shape[1], img.shape[0]]
|
| 94 |
+
if filename not in self._benchmark_results:
|
| 95 |
+
self._benchmark_results[filename] = dict()
|
| 96 |
+
self._benchmark_results[filename][str(size)] = self._metric.forward(model, *data[1:])
|
| 97 |
|
| 98 |
def printResults(self):
|
| 99 |
for imgName, results in self._benchmark_results.items():
|
|
|
|
| 115 |
benchmark = Benchmark(**cfg['Benchmark'])
|
| 116 |
|
| 117 |
# Instantiate model
|
| 118 |
+
model = build_from_cfg(cfg=cfg['Model'], registery=MODELS, key='name')
|
| 119 |
|
| 120 |
# Run benchmarking
|
| 121 |
print('Benchmarking {}:'.format(model.name))
|
benchmark/config/face_detection_yunet.yaml
CHANGED
|
@@ -1,13 +1,13 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Face Detection Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/face/detection"
|
| 5 |
files: ["group.jpg", "concerts.jpg", "dance.jpg"]
|
| 6 |
-
metric:
|
| 7 |
-
type: "Detection"
|
| 8 |
sizes: # [[w1, h1], ...], Omit to run at original scale
|
| 9 |
- [160, 120]
|
| 10 |
- [640, 480]
|
|
|
|
| 11 |
warmup: 30
|
| 12 |
repeat: 10
|
| 13 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Face Detection Benchmark"
|
| 3 |
+
type: "Detection"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/face/detection"
|
| 6 |
files: ["group.jpg", "concerts.jpg", "dance.jpg"]
|
|
|
|
|
|
|
| 7 |
sizes: # [[w1, h1], ...], Omit to run at original scale
|
| 8 |
- [160, 120]
|
| 9 |
- [640, 480]
|
| 10 |
+
metric:
|
| 11 |
warmup: 30
|
| 12 |
repeat: 10
|
| 13 |
reduction: "median"
|
benchmark/config/face_recognition_sface.yaml
CHANGED
|
@@ -1,11 +1,10 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Face Recognition Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/face/recognition"
|
| 5 |
files: ["Aaron_Tippin_0001.jpg", "Alvaro_Uribe_0028.jpg", "Alvaro_Uribe_0029.jpg", "Jose_Luis_Rodriguez_Zapatero_0001.jpg"]
|
| 6 |
-
useLabel: True
|
| 7 |
metric: # 'sizes' is omitted since this model requires input of fixed size
|
| 8 |
-
type: "Recognition"
|
| 9 |
warmup: 30
|
| 10 |
repeat: 10
|
| 11 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Face Recognition Benchmark"
|
| 3 |
+
type: "Recognition"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/face/recognition"
|
| 6 |
files: ["Aaron_Tippin_0001.jpg", "Alvaro_Uribe_0028.jpg", "Alvaro_Uribe_0029.jpg", "Jose_Luis_Rodriguez_Zapatero_0001.jpg"]
|
|
|
|
| 7 |
metric: # 'sizes' is omitted since this model requires input of fixed size
|
|
|
|
| 8 |
warmup: 30
|
| 9 |
repeat: 10
|
| 10 |
reduction: "median"
|
benchmark/config/human_segmentation_pphumanseg.yaml
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Human Segmentation Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/human_segmentation"
|
| 5 |
files: ["messi5.jpg", "100040721_1.jpg", "detect.jpg"]
|
|
|
|
| 6 |
toRGB: True
|
| 7 |
-
resize: [192, 192]
|
| 8 |
metric:
|
| 9 |
-
type: "Base"
|
| 10 |
warmup: 30
|
| 11 |
repeat: 10
|
| 12 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Human Segmentation Benchmark"
|
| 3 |
+
type: "Base"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/human_segmentation"
|
| 6 |
files: ["messi5.jpg", "100040721_1.jpg", "detect.jpg"]
|
| 7 |
+
sizes: [[192, 192]]
|
| 8 |
toRGB: True
|
|
|
|
| 9 |
metric:
|
|
|
|
| 10 |
warmup: 30
|
| 11 |
repeat: 10
|
| 12 |
reduction: "median"
|
benchmark/config/image_classification_ppresnet.yaml
CHANGED
|
@@ -1,13 +1,13 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Image Classification Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/image_classification"
|
| 5 |
files: ["coffee_mug.jpg", "umbrella.jpg", "wall_clock.jpg"]
|
|
|
|
| 6 |
toRGB: True
|
| 7 |
-
resize: [256, 256]
|
| 8 |
centerCrop: 224
|
| 9 |
metric:
|
| 10 |
-
type: "Base"
|
| 11 |
warmup: 30
|
| 12 |
repeat: 10
|
| 13 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Image Classification Benchmark"
|
| 3 |
+
type: "Classification"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/image_classification"
|
| 6 |
files: ["coffee_mug.jpg", "umbrella.jpg", "wall_clock.jpg"]
|
| 7 |
+
sizes: [[256, 256]]
|
| 8 |
toRGB: True
|
|
|
|
| 9 |
centerCrop: 224
|
| 10 |
metric:
|
|
|
|
| 11 |
warmup: 30
|
| 12 |
repeat: 10
|
| 13 |
reduction: "median"
|
benchmark/config/qrcode_wechatqrcode.yaml
CHANGED
|
@@ -1,13 +1,13 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "QRCode Detection and Decoding Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/qrcode"
|
| 5 |
files: ["opencv.png", "opencv_zoo.png"]
|
| 6 |
-
metric:
|
| 7 |
-
type: "Detection"
|
| 8 |
sizes:
|
| 9 |
- [100, 100]
|
| 10 |
- [300, 300]
|
|
|
|
| 11 |
warmup: 30
|
| 12 |
repeat: 10
|
| 13 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "QRCode Detection and Decoding Benchmark"
|
| 3 |
+
type: "Detection"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/qrcode"
|
| 6 |
files: ["opencv.png", "opencv_zoo.png"]
|
|
|
|
|
|
|
| 7 |
sizes:
|
| 8 |
- [100, 100]
|
| 9 |
- [300, 300]
|
| 10 |
+
metric:
|
| 11 |
warmup: 30
|
| 12 |
repeat: 10
|
| 13 |
reduction: "median"
|
benchmark/config/text_detection_db.yaml
CHANGED
|
@@ -1,12 +1,12 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Text Detection Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/text"
|
| 5 |
files: ["1.jpg", "2.jpg", "3.jpg"]
|
| 6 |
-
metric:
|
| 7 |
-
type: "Detection"
|
| 8 |
sizes: # [[w1, h1], ...], Omit to run at original scale
|
| 9 |
- [640, 480]
|
|
|
|
| 10 |
warmup: 30
|
| 11 |
repeat: 10
|
| 12 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Text Detection Benchmark"
|
| 3 |
+
type: "Detection"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/text"
|
| 6 |
files: ["1.jpg", "2.jpg", "3.jpg"]
|
|
|
|
|
|
|
| 7 |
sizes: # [[w1, h1], ...], Omit to run at original scale
|
| 8 |
- [640, 480]
|
| 9 |
+
metric:
|
| 10 |
warmup: 30
|
| 11 |
repeat: 10
|
| 12 |
reduction: "median"
|
benchmark/config/text_recognition_crnn.yaml
CHANGED
|
@@ -1,11 +1,10 @@
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Text Recognition Benchmark"
|
|
|
|
| 3 |
data:
|
| 4 |
path: "benchmark/data/text"
|
| 5 |
files: ["1.jpg", "2.jpg", "3.jpg"]
|
| 6 |
-
useLabel: True
|
| 7 |
metric: # 'sizes' is omitted since this model requires input of fixed size
|
| 8 |
-
type: "Recognition"
|
| 9 |
warmup: 30
|
| 10 |
repeat: 10
|
| 11 |
reduction: "median"
|
|
|
|
| 1 |
Benchmark:
|
| 2 |
name: "Text Recognition Benchmark"
|
| 3 |
+
type: "Recognition"
|
| 4 |
data:
|
| 5 |
path: "benchmark/data/text"
|
| 6 |
files: ["1.jpg", "2.jpg", "3.jpg"]
|
|
|
|
| 7 |
metric: # 'sizes' is omitted since this model requires input of fixed size
|
|
|
|
| 8 |
warmup: 30
|
| 9 |
repeat: 10
|
| 10 |
reduction: "median"
|
benchmark/utils/__init__.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
from .factory import (METRICS, DATALOADERS)
|
| 2 |
from .metrics import *
|
|
|
|
| 3 |
|
| 4 |
__all__ = ['METRICS', 'DATALOADERS']
|
|
|
|
| 1 |
from .factory import (METRICS, DATALOADERS)
|
| 2 |
from .metrics import *
|
| 3 |
+
from .dataloaders import *
|
| 4 |
|
| 5 |
__all__ = ['METRICS', 'DATALOADERS']
|
benchmark/utils/dataloaders/__init__.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .base import BaseImageLoader, BaseVideoLoader
|
| 2 |
+
from .classification import ClassificationImageLoader
|
| 3 |
+
from .recognition import RecognitionImageLoader
|
| 4 |
+
from .tracking import TrackingVideoLoader
|
| 5 |
+
|
| 6 |
+
__all__ = ['BaseImageLoader', 'BaseVideoLoader', 'ClassificationImageLoader', 'RecognitionImageLoader', 'TrackingVideoLoader']
|
benchmark/utils/dataloaders/base.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .base_dataloader import _BaseImageLoader, _BaseVideoLoader
|
| 2 |
+
from ..factory import DATALOADERS
|
| 3 |
+
|
| 4 |
+
@DATALOADERS.register
|
| 5 |
+
class BaseImageLoader(_BaseImageLoader):
|
| 6 |
+
def __init__(self, **kwargs):
|
| 7 |
+
super().__init__(**kwargs)
|
| 8 |
+
|
| 9 |
+
@DATALOADERS.register
|
| 10 |
+
class BaseVideoLoader(_BaseVideoLoader):
|
| 11 |
+
def __init__(self, **kwargs):
|
| 12 |
+
super().__init__(**kwargs)
|
benchmark/utils/dataloaders/base_dataloader.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
import cv2 as cv
|
| 4 |
+
|
| 5 |
+
class _BaseImageLoader:
|
| 6 |
+
def __init__(self, **kwargs):
|
| 7 |
+
self._path = kwargs.pop('path', None)
|
| 8 |
+
assert self._path, 'Benchmark[\'data\'][\'path\'] cannot be empty.'
|
| 9 |
+
|
| 10 |
+
self._files = kwargs.pop('files', None)
|
| 11 |
+
assert self._files, 'Benchmark[\'data\'][\'files\'] cannot be empty'
|
| 12 |
+
self._len_files = len(self._files)
|
| 13 |
+
|
| 14 |
+
self._sizes = kwargs.pop('sizes', [[0, 0]])
|
| 15 |
+
self._len_sizes = len(self._sizes)
|
| 16 |
+
|
| 17 |
+
@property
|
| 18 |
+
def name(self):
|
| 19 |
+
return self.__class__.__name__
|
| 20 |
+
|
| 21 |
+
def __len__(self):
|
| 22 |
+
return self._len_files * self._len_sizes
|
| 23 |
+
|
| 24 |
+
def __iter__(self):
|
| 25 |
+
for filename in self._files:
|
| 26 |
+
image = cv.imread(os.path.join(self._path, filename))
|
| 27 |
+
if [0, 0] in self._sizes:
|
| 28 |
+
yield filename, image
|
| 29 |
+
else:
|
| 30 |
+
for size in self._sizes:
|
| 31 |
+
image_r = cv.resize(image, size)
|
| 32 |
+
yield filename, image_r
|
| 33 |
+
|
| 34 |
+
class _VideoStream:
|
| 35 |
+
def __init__(self, filepath):
|
| 36 |
+
self._filepath = filepath
|
| 37 |
+
self._video = cv.VideoCapture(filepath)
|
| 38 |
+
|
| 39 |
+
def __iter__(self):
|
| 40 |
+
while True:
|
| 41 |
+
has_frame, frame = self._video.read()
|
| 42 |
+
if has_frame:
|
| 43 |
+
yield frame
|
| 44 |
+
else:
|
| 45 |
+
break
|
| 46 |
+
|
| 47 |
+
def reload(self):
|
| 48 |
+
self._video = cv.VideoCapture(filepath)
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
class _BaseVideoLoader:
|
| 52 |
+
def __init__(self, **kwargs):
|
| 53 |
+
self._path = kwargs.pop('path', None)
|
| 54 |
+
assert self._path, 'Benchmark[\'data\'][\'path\'] cannot be empty.'
|
| 55 |
+
|
| 56 |
+
self._files = kwargs.pop('files', None)
|
| 57 |
+
assert self._files,'Benchmark[\'data\'][\'files\'] cannot be empty.'
|
| 58 |
+
|
| 59 |
+
@property
|
| 60 |
+
def name(self):
|
| 61 |
+
return self.__class__.__name__
|
| 62 |
+
|
| 63 |
+
def __len__(self):
|
| 64 |
+
return len(self._files)
|
| 65 |
+
|
| 66 |
+
def __getitem__(self, idx):
|
| 67 |
+
return self._files[idx], _VideoStream(os.path.join(self._path, self._files[idx]))
|
benchmark/utils/dataloaders/classification.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
import cv2 as cv
|
| 5 |
+
|
| 6 |
+
from .base_dataloader import _BaseImageLoader
|
| 7 |
+
from ..factory import DATALOADERS
|
| 8 |
+
|
| 9 |
+
@DATALOADERS.register
|
| 10 |
+
class ClassificationImageLoader(_BaseImageLoader):
|
| 11 |
+
def __init__(self, **kwargs):
|
| 12 |
+
super().__init__(**kwargs)
|
| 13 |
+
|
| 14 |
+
self._to_rgb = kwargs.pop('toRGB', False)
|
| 15 |
+
self._center_crop = kwargs.pop('centerCrop', None)
|
| 16 |
+
|
| 17 |
+
def _toRGB(self, image):
|
| 18 |
+
return cv.cvtColor(image, cv.COLOR_BGR2RGB)
|
| 19 |
+
|
| 20 |
+
def _centerCrop(self, image):
|
| 21 |
+
h, w, _ = image.shape
|
| 22 |
+
w_crop = int((w - self._center_crop) / 2.)
|
| 23 |
+
assert w_crop >= 0
|
| 24 |
+
h_crop = int((h - self._center_crop) / 2.)
|
| 25 |
+
assert h_crop >= 0
|
| 26 |
+
return image[w_crop:w-w_crop, h_crop:h-h_crop, :]
|
| 27 |
+
|
| 28 |
+
def __iter__(self):
|
| 29 |
+
for filename in self._files:
|
| 30 |
+
image = cv.imread(os.path.join(self._path, filename))
|
| 31 |
+
|
| 32 |
+
if self._to_rgb:
|
| 33 |
+
image = self._toRGB(image)
|
| 34 |
+
|
| 35 |
+
if [0, 0] in self._sizes:
|
| 36 |
+
yield filename, image
|
| 37 |
+
else:
|
| 38 |
+
for size in self._sizes:
|
| 39 |
+
image = cv.resize(image, size)
|
| 40 |
+
if self._center_crop:
|
| 41 |
+
image = self._centerCrop(image)
|
| 42 |
+
yield filename, image
|
benchmark/utils/dataloaders/recognition.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
import numpy as np
|
| 4 |
+
import cv2 as cv
|
| 5 |
+
|
| 6 |
+
from .base_dataloader import _BaseImageLoader
|
| 7 |
+
from ..factory import DATALOADERS
|
| 8 |
+
|
| 9 |
+
@DATALOADERS.register
|
| 10 |
+
class RecognitionImageLoader(_BaseImageLoader):
|
| 11 |
+
def __init__(self, **kwargs):
|
| 12 |
+
super().__init__(**kwargs)
|
| 13 |
+
|
| 14 |
+
self._labels = self._load_label()
|
| 15 |
+
|
| 16 |
+
def _load_label(self):
|
| 17 |
+
labels = dict.fromkeys(self._files, None)
|
| 18 |
+
for filename in self._files:
|
| 19 |
+
labels[filename] = np.loadtxt(os.path.join(self._path, '{}.txt'.format(filename[:-4])), ndmin=2)
|
| 20 |
+
return labels
|
| 21 |
+
|
| 22 |
+
def __iter__(self):
|
| 23 |
+
for filename in self._files:
|
| 24 |
+
image = cv.imread(os.path.join(self._path, filename))
|
| 25 |
+
if [0, 0] in self._sizes:
|
| 26 |
+
yield filename, image, self._labels[filename]
|
| 27 |
+
else:
|
| 28 |
+
for size in self._sizes:
|
| 29 |
+
image_r = cv.resize(image, size)
|
| 30 |
+
yield filename, image_r, self._labels[filename]
|
benchmark/utils/dataloaders/tracking.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
|
| 3 |
+
from .base_dataloader import _BaseVideoLoader
|
| 4 |
+
from ..factory import DATALOADERS
|
| 5 |
+
|
| 6 |
+
@DATALOADERS.register
|
| 7 |
+
class TrackingVideoLoader(_BaseVideoLoader):
|
| 8 |
+
def __init__(self, **kwargs):
|
| 9 |
+
super().__init__(**kwargs)
|
| 10 |
+
|
| 11 |
+
self._rois = self._load_roi()
|
| 12 |
+
|
| 13 |
+
unsupported_keys = []
|
| 14 |
+
for k, _ in kwargs.items():
|
| 15 |
+
unsupported_keys.append(k)
|
| 16 |
+
print('Keys ({}) are not supported in Benchmark[\'data\'].'.format(str(unsupported_keys)))
|
| 17 |
+
|
| 18 |
+
def _load_roi(self):
|
| 19 |
+
rois = dict.fromkeys(self._files, None)
|
| 20 |
+
for filename in self._files:
|
| 21 |
+
rois[filename] = np.loadtxt(os.path.join(self._path, '{}.txt'.format(filename[:-4])), ndmin=2)
|
| 22 |
+
return rois
|
| 23 |
+
|
| 24 |
+
def getROI(self):
|
| 25 |
+
return self._rois
|
benchmark/utils/factory.py
CHANGED
|
@@ -4,10 +4,17 @@ class Registery:
|
|
| 4 |
self._dict = dict()
|
| 5 |
|
| 6 |
def get(self, key):
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
def register(self, item):
|
| 10 |
self._dict[item.__name__] = item
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
METRICS = Registery('Metrics')
|
| 13 |
DATALOADERS = Registery('DataLoaders')
|
|
|
|
| 4 |
self._dict = dict()
|
| 5 |
|
| 6 |
def get(self, key):
|
| 7 |
+
if key in self._dict:
|
| 8 |
+
return self._dict[key]
|
| 9 |
+
else:
|
| 10 |
+
return self._dict['Base']
|
| 11 |
|
| 12 |
def register(self, item):
|
| 13 |
self._dict[item.__name__] = item
|
| 14 |
+
# renaming *ImageLoader/*VideoLoader
|
| 15 |
+
if 'ImageLoader' in item.__name__:
|
| 16 |
+
name = item.__name__.replace('ImageLoader', '')
|
| 17 |
+
self._dict[name] = item
|
| 18 |
|
| 19 |
METRICS = Registery('Metrics')
|
| 20 |
DATALOADERS = Registery('DataLoaders')
|
benchmark/utils/metrics/base.py
CHANGED
|
@@ -10,20 +10,15 @@ class Base(BaseMetric):
|
|
| 10 |
|
| 11 |
def forward(self, model, *args, **kwargs):
|
| 12 |
img = args[0]
|
| 13 |
-
if not self._sizes:
|
| 14 |
-
h, w, _ = img.shape
|
| 15 |
-
self._sizes.append([w, h])
|
| 16 |
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
| 18 |
self._timer.reset()
|
| 19 |
-
for
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
for _ in range(self._repeat):
|
| 24 |
-
self._timer.start()
|
| 25 |
-
model.infer(input_data)
|
| 26 |
-
self._timer.stop()
|
| 27 |
-
results[str(size)] = self._getResult()
|
| 28 |
|
| 29 |
-
return
|
|
|
|
| 10 |
|
| 11 |
def forward(self, model, *args, **kwargs):
|
| 12 |
img = args[0]
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
+
# warmup
|
| 15 |
+
for _ in range(self._warmup):
|
| 16 |
+
model.infer(img)
|
| 17 |
+
# repeat
|
| 18 |
self._timer.reset()
|
| 19 |
+
for _ in range(self._repeat):
|
| 20 |
+
self._timer.start()
|
| 21 |
+
model.infer(img)
|
| 22 |
+
self._timer.stop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
return self._getResult()
|
benchmark/utils/metrics/base_metric.py
CHANGED
|
@@ -4,9 +4,6 @@ from ..timer import Timer
|
|
| 4 |
|
| 5 |
class BaseMetric:
|
| 6 |
def __init__(self, **kwargs):
|
| 7 |
-
self._sizes = kwargs.pop('sizes', None)
|
| 8 |
-
if self._sizes is None:
|
| 9 |
-
self._sizes = []
|
| 10 |
self._warmup = kwargs.pop('warmup', 3)
|
| 11 |
self._repeat = kwargs.pop('repeat', 10)
|
| 12 |
self._reduction = kwargs.pop('reduction', 'median')
|
|
|
|
| 4 |
|
| 5 |
class BaseMetric:
|
| 6 |
def __init__(self, **kwargs):
|
|
|
|
|
|
|
|
|
|
| 7 |
self._warmup = kwargs.pop('warmup', 3)
|
| 8 |
self._repeat = kwargs.pop('repeat', 10)
|
| 9 |
self._reduction = kwargs.pop('reduction', 'median')
|
benchmark/utils/metrics/detection.py
CHANGED
|
@@ -10,24 +10,20 @@ class Detection(BaseMetric):
|
|
| 10 |
|
| 11 |
def forward(self, model, *args, **kwargs):
|
| 12 |
img = args[0]
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
| 16 |
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
| 18 |
self._timer.reset()
|
| 19 |
-
for
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
except:
|
| 24 |
-
pass
|
| 25 |
-
for _ in range(self._warmup):
|
| 26 |
-
model.infer(input_data)
|
| 27 |
-
for _ in range(self._repeat):
|
| 28 |
-
self._timer.start()
|
| 29 |
-
model.infer(input_data)
|
| 30 |
-
self._timer.stop()
|
| 31 |
-
results[str(size)] = self._getResult()
|
| 32 |
|
| 33 |
-
return
|
|
|
|
| 10 |
|
| 11 |
def forward(self, model, *args, **kwargs):
|
| 12 |
img = args[0]
|
| 13 |
+
size = [img.shape[1], img.shape[0]]
|
| 14 |
+
try:
|
| 15 |
+
model.setInputSize(size)
|
| 16 |
+
except:
|
| 17 |
+
pass
|
| 18 |
|
| 19 |
+
# warmup
|
| 20 |
+
for _ in range(self._warmup):
|
| 21 |
+
model.infer(img)
|
| 22 |
+
# repeat
|
| 23 |
self._timer.reset()
|
| 24 |
+
for _ in range(self._repeat):
|
| 25 |
+
self._timer.start()
|
| 26 |
+
model.infer(img)
|
| 27 |
+
self._timer.stop()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
return self._getResult()
|
benchmark/utils/metrics/recognition.py
CHANGED
|
@@ -10,11 +10,7 @@ class Recognition(BaseMetric):
|
|
| 10 |
|
| 11 |
def forward(self, model, *args, **kwargs):
|
| 12 |
img, bboxes = args
|
| 13 |
-
if not self._sizes:
|
| 14 |
-
h, w, _ = img.shape
|
| 15 |
-
self._sizes.append([w, h])
|
| 16 |
|
| 17 |
-
results = dict()
|
| 18 |
self._timer.reset()
|
| 19 |
for idx, bbox in enumerate(bboxes):
|
| 20 |
for _ in range(self._warmup):
|
|
@@ -23,6 +19,5 @@ class Recognition(BaseMetric):
|
|
| 23 |
self._timer.start()
|
| 24 |
model.infer(img, bbox)
|
| 25 |
self._timer.stop()
|
| 26 |
-
results['bbox{}'.format(idx)] = self._getResult()
|
| 27 |
|
| 28 |
-
return
|
|
|
|
| 10 |
|
| 11 |
def forward(self, model, *args, **kwargs):
|
| 12 |
img, bboxes = args
|
|
|
|
|
|
|
|
|
|
| 13 |
|
|
|
|
| 14 |
self._timer.reset()
|
| 15 |
for idx, bbox in enumerate(bboxes):
|
| 16 |
for _ in range(self._warmup):
|
|
|
|
| 19 |
self._timer.start()
|
| 20 |
model.infer(img, bbox)
|
| 21 |
self._timer.stop()
|
|
|
|
| 22 |
|
| 23 |
+
return self._getResult()
|