-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
When using custom classes, the label map is created in this way (copied below). This code fragment is fragile because missing classes are mapped to "-1", but the "-1" is never handled properly.
# dictionary, its keys are the old label ids and its values
# are the new label ids.
# used for changing pixel labels in load_annotations.
self.label_map = {}
for i, c in enumerate(self.CLASSES):
if c not in class_names:
self.label_map[i] = -1
else:
self.label_map[i] = class_names.index(c)I've tried to understand how this "-1" label is handled when training. The expected behavior is that this "-1" label should be ignored. However, this behavior is achieved very indirectly and precariously (prone to bugs):
In loading.py:
gt_semantic_seg = mmcv.imfrombytes(
img_bytes, flag='unchanged',
backend=self.imdecode_backend).squeeze().astype(np.uint8)gt_semantic_seg is created with type uint8. Then,
if results.get('label_map', None) is not None:
for old_id, new_id in results['label_map'].items():
gt_semantic_seg[gt_semantic_seg == old_id] = new_idWhen new_id is -1, uint8 underflows to 255. Then, since the default ignore_index=255 in custom.py, the "-1" label is successfully ignored.
My issue is that this process is not explicit and can be prone to bugs. For example, the uint8 masks are eventually converted to torch.Tensor of type int64, which can contain negative values. The code only works just because an intermediate step happened to use uint8 and the underflow occurred.
I think the code should be improved and the "-1" label should be handled more explicitly, by, for example, always ignoring negative labels in addition to ignoring the (optional) ignore_index label.