Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
dbolya
GitHub Repository: dbolya/tide
Path: blob/master/tidecv/data.py
110 views
1
import os
2
3
from collections import defaultdict
4
import numpy as np
5
import cv2
6
7
from . import functions as f
8
9
class Data():
10
"""
11
A class to hold ground truth or predictions data in an easy to work with format.
12
Note that any time they appear, bounding boxes are [x, y, width, height] and masks
13
are either a list of polygons or pycocotools RLEs.
14
15
Also, don't mix ground truth with predictions. Keep them in separate data objects.
16
17
'max_dets' specifies the maximum number of detections the model is allowed to output for a given image.
18
"""
19
20
def __init__(self, name:str, max_dets:int=100):
21
self.name = name
22
self.max_dets = max_dets
23
24
self.classes = {} # Maps class ID to class name
25
self.annotations = [] # Maps annotation ids to the corresponding annotation / prediction
26
27
# Maps an image id to an image name and a list of annotation ids
28
self.images = defaultdict(lambda: {'name': None, 'anns': []})
29
30
31
def _get_ignored_classes(self, image_id:int) -> set:
32
anns = self.get(image_id)
33
34
classes_in_image = set()
35
ignored_classes = set()
36
37
for ann in anns:
38
if ann['ignore']:
39
if ann['class'] is not None and ann['bbox'] is None and ann['mask'] is None:
40
ignored_classes.add(ann['class'])
41
else:
42
classes_in_image.add(ann['class'])
43
44
return ignored_classes.difference(classes_in_image)
45
46
47
def _make_default_class(self, id:int):
48
""" (For internal use) Initializes a class id with a generated name. """
49
50
if id not in self.classes:
51
self.classes[id] = 'Class ' + str(id)
52
53
def _make_default_image(self, id:int):
54
if self.images[id]['name'] is None:
55
self.images[id]['name'] = 'Image ' + str(id)
56
57
def _prepare_box(self, box:object):
58
return box
59
60
def _prepare_mask(self, mask:object):
61
return mask
62
63
def _add(self, image_id:int, class_id:int, box:object=None, mask:object=None, score:float=1, ignore:bool=False):
64
""" Add a data object to this collection. You should use one of the below functions instead. """
65
self._make_default_class(class_id)
66
self._make_default_image(image_id)
67
new_id = len(self.annotations)
68
69
self.annotations.append({
70
'_id' : new_id,
71
'score' : score,
72
'image' : image_id,
73
'class' : class_id,
74
'bbox' : self._prepare_box(box),
75
'mask' : self._prepare_mask(mask),
76
'ignore': ignore,
77
})
78
79
self.images[image_id]['anns'].append(new_id)
80
81
def add_ground_truth(self, image_id:int, class_id:int, box:object=None, mask:object=None):
82
""" Add a ground truth. If box or mask is None, this GT will be ignored for that mode. """
83
self._add(image_id, class_id, box, mask)
84
85
def add_detection(self, image_id:int, class_id:int, score:int, box:object=None, mask:object=None):
86
""" Add a predicted detection. If box or mask is None, this prediction will be ignored for that mode. """
87
self._add(image_id, class_id, box, mask, score=score)
88
89
def add_ignore_region(self, image_id:int, class_id:int=None, box:object=None, mask:object=None):
90
"""
91
Add a region inside of which background detections should be ignored.
92
You can use these to mark a region that has deliberately been left unannotated
93
(e.g., if is a huge crowd of people and you don't want to annotate every single person in the crowd).
94
95
If class_id is -1, this region will match any class. If the box / mask is None, the region will be the entire image.
96
"""
97
self._add(image_id, class_id, box, mask, ignore=True)
98
99
def add_class(self, id:int, name:str):
100
""" Register a class name to that class ID. """
101
self.classes[id] = name
102
103
def add_image(self, id:int, name:str):
104
""" Register an image name/path with an image ID. """
105
self.images[id]['name'] = name
106
107
108
def get(self, image_id:int):
109
""" Collects all the annotations / detections for that particular image. """
110
return [self.annotations[x] for x in self.images[image_id]['anns']]
111
112