8
8
from tqdm import tqdm
9
9
10
10
11
- # Available classes for YOEO
12
- CLASSES = {
13
- 'bb_classes' : ['ball' , 'goalpost' , 'robot' ],
14
- 'segmentation_classes' : ['background' , 'lines' , 'field' ],
15
- 'skip_classes' : ['obstacle' , 'L-Intersection' , 'X-Intersection' , 'T-Intersection' ]
16
- }
17
-
18
-
19
11
def range_limited_float_type_0_to_1 (arg ):
20
12
"""Type function for argparse - a float within some predefined bounds
21
13
Derived from 'https://stackoverflow.com/questions/55324449/how-to-specify-a-minimum-or-maximum-float-value-with-argparse/55410582#55410582'.
@@ -37,8 +29,16 @@ def range_limited_float_type_0_to_1(arg):
37
29
parser .add_argument ("--skip-blurred" , action = "store_true" , help = "Skip blurred labels" )
38
30
parser .add_argument ("--skip-concealed" , action = "store_true" , help = "Skip concealed labels" )
39
31
parser .add_argument ("--skip-classes" , nargs = "+" , default = [], help = "These bounding box classes will be skipped" )
32
+ parser .add_argument ("--robots-with-team-colors" , action = "store_true" , help = "The robot class will be subdivided into subclasses, one for each team color (currently either 'blue', 'red' or 'unknown')." )
40
33
args = parser .parse_args ()
41
34
35
+ # Available classes for YOEO
36
+ CLASSES = {
37
+ 'bb_classes' : ['ball' , 'goalpost' , 'robot' ] if not args .robots_with_team_colors else ['ball' , 'goalpost' , 'robot_blue' , 'robot_red' , 'robot_unknown' ],
38
+ 'segmentation_classes' : ['background' , 'lines' , 'field' ],
39
+ 'skip_classes' : ['obstacle' , 'L-Intersection' , 'X-Intersection' , 'T-Intersection' ],
40
+ }
41
+
42
42
# Remove skipped classes from CLASSES list
43
43
for skip_class in args .skip_classes :
44
44
if skip_class in CLASSES ['bb_classes' ]:
@@ -122,33 +122,42 @@ def range_limited_float_type_0_to_1(arg):
122
122
annotations = []
123
123
124
124
for annotation in image_data ['annotations' ]:
125
+ # Skip annotations that are not in the image
126
+ if not annotation ['in_image' ]:
127
+ continue
128
+
129
+ # Derive the class name of the current annotation
130
+ class_name = annotation ['type' ]
131
+ if args .robots_with_team_colors and class_name == 'robot' :
132
+ class_name += f"_{ annotation ['color' ]} "
133
+
125
134
# Skip annotations, if is not a bounding box or should be skipped or is blurred or concealed and user chooses to skip them
126
- if (annotation [ 'type' ] in CLASSES ['segmentation_classes' ] or # Handled by segmentations
127
- annotation [ 'type' ] in CLASSES ['skip_classes' ] or # Skip this annotation class
135
+ if (class_name in CLASSES ['segmentation_classes' ] or # Handled by segmentations
136
+ class_name in CLASSES ['skip_classes' ] or # Skip this annotation class
128
137
(args .skip_blurred and annotation .get ('blurred' , False )) or
129
138
(args .skip_concealed and annotation .get ('concealed' , False ))):
130
139
continue
131
- elif annotation [ 'type' ] in CLASSES ['bb_classes' ]: # Handle bounding boxes
132
- if annotation [ 'in_image' ]: # If annotation is not in image, do nothing
133
- min_x = min (map (lambda x : x [0 ], annotation ['vector' ]))
134
- max_x = max (map (lambda x : x [0 ], annotation ['vector' ]))
135
- min_y = min (map (lambda x : x [1 ], annotation ['vector' ]))
136
- max_y = max ( map ( lambda x : x [ 1 ], annotation [ 'vector' ]))
137
-
138
- annotation_width = max_x - min_x
139
- annotation_height = max_y - min_y
140
- relative_annotation_width = annotation_width / img_width
141
- relative_annotation_height = annotation_height / img_height
142
-
143
- center_x = min_x + (annotation_width / 2 )
144
- center_y = min_y + ( annotation_height / 2 )
145
- relative_center_x = center_x / img_width
146
- relative_center_y = center_y / img_height
147
-
148
- classID = CLASSES ['bb_classes' ].index (annotation [ 'type' ] ) # Derive classID from index in predefined classes
149
- annotations .append (f"{ classID } { relative_center_x } { relative_center_y } { relative_annotation_width } { relative_annotation_height } " )
140
+ elif class_name in CLASSES ['bb_classes' ]: # Handle bounding boxes
141
+ min_x = min ( map ( lambda x : x [ 0 ], annotation [ 'vector' ]))
142
+ max_x = max (map (lambda x : x [0 ], annotation ['vector' ]))
143
+ min_y = min (map (lambda x : x [1 ], annotation ['vector' ]))
144
+ max_y = max (map (lambda x : x [1 ], annotation ['vector' ]))
145
+
146
+ annotation_width = max_x - min_x
147
+ annotation_height = max_y - min_y
148
+ relative_annotation_width = annotation_width / img_width
149
+ relative_annotation_height = annotation_height / img_height
150
+
151
+ center_x = min_x + ( annotation_width / 2 )
152
+ center_y = min_y + (annotation_height / 2 )
153
+ relative_center_x = center_x / img_width
154
+ relative_center_y = center_y / img_height
155
+
156
+ # Derive classID from index in predefined classes
157
+ classID = CLASSES ['bb_classes' ].index (class_name )
158
+ annotations .append (f"{ classID } { relative_center_x } { relative_center_y } { relative_annotation_width } { relative_annotation_height } " )
150
159
else :
151
- print (f"The annotation type '{ annotation [ 'type' ] } ' is not supported. Image: '{ img_name_with_extension } '" )
160
+ print (f"The annotation type '{ class_name } ' is not supported. Image: '{ img_name_with_extension } '" )
152
161
153
162
# Store bounding box annotations in .txt file
154
163
with open (os .path .join (labels_dir , img_name_without_extension + ".txt" ), "w" ) as output :
0 commit comments