dietr 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dietr/__init__.py +1 -0
- dietr/data/__init__.py +0 -0
- dietr/data/box_conversion.py +101 -0
- dietr/data/coco_definitions.py +287 -0
- dietr/data/conversion.py +128 -0
- dietr/data/dataloaders.py +107 -0
- dietr/data/loading.py +32 -0
- dietr/data/msk_conversion.py +132 -0
- dietr/data/transforms/__init__.py +0 -0
- dietr/data/transforms/base.py +211 -0
- dietr/data/transforms/mosaic.py +176 -0
- dietr/data/transforms/photometric.py +115 -0
- dietr/data/transforms/random_crop.py +98 -0
- dietr/data/transforms/random_zoom.py +123 -0
- dietr/data/trn_batch_collate.py +146 -0
- dietr/data/trn_dataset.py +164 -0
- dietr/data/val_batch_collate.py +79 -0
- dietr/data/val_dataset.py +50 -0
- dietr/modeling/__init__.py +0 -0
- dietr/modeling/base/__init__.py +0 -0
- dietr/modeling/base/blocks.py +232 -0
- dietr/modeling/base/deformable_attention.py +366 -0
- dietr/modeling/base/layers.py +42 -0
- dietr/modeling/base/projections.py +63 -0
- dietr/modeling/base/query_denoising.py +193 -0
- dietr/modeling/dietr/__init__.py +0 -0
- dietr/modeling/dietr/back_convnext.py +76 -0
- dietr/modeling/dietr/dietr.py +177 -0
- dietr/modeling/dietr/head.py +390 -0
- dietr/modeling/dietr/mask.py +62 -0
- dietr/modeling/dietr/neck.py +94 -0
- dietr/modeling/ema.py +75 -0
- dietr/modeling/loss/__init__.py +0 -0
- dietr/modeling/loss/loss.py +264 -0
- dietr/modeling/loss/matcher.py +107 -0
- dietr/tools/__init__.py +0 -0
- dietr/tools/distributed.py +103 -0
- dietr/tools/logging.py +194 -0
- dietr/tools/plot_coco.py +76 -0
- dietr/tools/plot_internal.py +37 -0
- dietr/tools/split_coco.py +65 -0
- dietr/tools/training.py +278 -0
- dietr/tools/validation.py +278 -0
- dietr/trn.py +151 -0
- dietr/val.py +50 -0
- dietr/wrapper.py +109 -0
- dietr-0.2.0.dist-info/METADATA +392 -0
- dietr-0.2.0.dist-info/RECORD +50 -0
- dietr-0.2.0.dist-info/WHEEL +4 -0
- dietr-0.2.0.dist-info/licenses/LICENSE +201 -0
dietr/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .wrapper import DIETR
|
dietr/data/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
------------------------------------------------------------------------
|
|
3
|
+
DIETR
|
|
4
|
+
Copyright (c) 2026 Koen Botermans
|
|
5
|
+
Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
|
6
|
+
------------------------------------------------------------------------
|
|
7
|
+
"""
|
|
8
|
+
import numpy as np
|
|
9
|
+
import torch
|
|
10
|
+
|
|
11
|
+
def box_coco_to_yolo(box: list[int], img_hw: tuple[int]) -> list[float]:
|
|
12
|
+
"""
|
|
13
|
+
Convert Coco pixel formal boxes to yolo normalized.
|
|
14
|
+
Coco/Pixel format: [x_min, y_min, width, height]
|
|
15
|
+
YOLO format normalized: [x_center, y_center, width, height]
|
|
16
|
+
xyxy format: [x_min, y_min, x_max, y_max]
|
|
17
|
+
This is often called cxcywh format.
|
|
18
|
+
"""
|
|
19
|
+
x, y, w, h = box[:4]
|
|
20
|
+
x /= img_hw[1]
|
|
21
|
+
y /= img_hw[0]
|
|
22
|
+
w /= img_hw[1]
|
|
23
|
+
h /= img_hw[0]
|
|
24
|
+
return [x + w / 2, y + h / 2, w, h]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def box_yolo_to_coco(box_np: np.ndarray, img_hw: tuple[int, int]) -> np.ndarray:
|
|
28
|
+
"""
|
|
29
|
+
Convert yolo format to coco format.
|
|
30
|
+
Coco/Pixel format: [x_min, y_min, width, height]
|
|
31
|
+
YOLO format normalized: [x_center, y_center, width, height]
|
|
32
|
+
xyxy format: [x_min, y_min, x_max, y_max]
|
|
33
|
+
"""
|
|
34
|
+
x_min = (box_np[:, 0] - box_np[:, 2] / 2) * img_hw[1]
|
|
35
|
+
y_min = (box_np[:, 1] - box_np[:, 3] / 2) * img_hw[0]
|
|
36
|
+
w = (box_np[:, 2] * img_hw[1])
|
|
37
|
+
h = (box_np[:, 3] * img_hw[0])
|
|
38
|
+
return np.floor(np.vstack([x_min, y_min, w, h]).T).astype(int)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def box_tensor_yolo_to_xyxy(box: torch.Tensor) -> torch.Tensor:
|
|
42
|
+
"""
|
|
43
|
+
Coco/Pixel format: [x_min, y_min, width, height]
|
|
44
|
+
YOLO format normalized: [x_center, y_center, width, height]
|
|
45
|
+
xyxy format: [x_min, y_min, x_max, y_max]
|
|
46
|
+
Can also be the pascal voc format!
|
|
47
|
+
"""
|
|
48
|
+
x_c, y_c, w, h = box.unbind(-1)
|
|
49
|
+
b = [(x_c - 0.5 * w), (y_c - 0.5 * h), (x_c + 0.5 * w), (y_c + 0.5 * h)]
|
|
50
|
+
return torch.stack(b, dim=-1)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def box_tensor_xyxy_to_yolo(box: torch.Tensor) -> torch.Tensor:
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
Coco/Pixel format: [x_min, y_min, width, height]
|
|
57
|
+
YOLO format normalized: [x_center, y_center, width, height]
|
|
58
|
+
xyxy format: [x_min, y_min, x_max, y_max]
|
|
59
|
+
Can also be the pascal voc format!
|
|
60
|
+
"""
|
|
61
|
+
xmin, ymin, xmax, ymax = box.unbind(-1)
|
|
62
|
+
box = [(xmax - xmin) / 2, (ymax - ymin) / 2, (xmax - xmin), (ymax - ymin)]
|
|
63
|
+
return torch.stack(box, dim=-1)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def box_xyxy_area(box: torch.Tensor) -> torch.Tensor:
|
|
67
|
+
"""Computes the area of a box in normalized pascal format"""
|
|
68
|
+
return (box[:, 2] - box[:, 0]) * (box[:, 3] - box[:, 1])
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def box_xyxy_iou(box1: torch.Tensor, box2: torch.Tensor):
|
|
72
|
+
area1 = box_xyxy_area(box1)
|
|
73
|
+
area2 = box_xyxy_area(box2)
|
|
74
|
+
|
|
75
|
+
lt = torch.max(box1[:, None, :2], box2[:, :2]) # [N,M,2]
|
|
76
|
+
rb = torch.min(box1[:, None, 2:], box2[:, 2:]) # [N,M,2]
|
|
77
|
+
|
|
78
|
+
wh = (rb - lt).clamp(min=0) # [N,M,2]
|
|
79
|
+
inter = wh[:, :, 0] * wh[:, :, 1] # [N,M]
|
|
80
|
+
|
|
81
|
+
union = area1[:, None] + area2 - inter
|
|
82
|
+
|
|
83
|
+
iou = inter / union
|
|
84
|
+
return iou, union
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def box_yolo_iou(box1: torch.Tensor, box2: torch.Tensor):
|
|
88
|
+
return box_xyxy_iou(
|
|
89
|
+
box_tensor_yolo_to_xyxy(box=box1), box_tensor_yolo_to_xyxy(box=box2)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def box_yolo_giou(box1: torch.Tensor, box2: torch.Tensor) -> torch.Tensor:
|
|
94
|
+
iou, union = box_yolo_iou(box1, box2)
|
|
95
|
+
box1 = box_tensor_yolo_to_xyxy(box=box1)
|
|
96
|
+
box2 = box_tensor_yolo_to_xyxy(box=box2)
|
|
97
|
+
lt = torch.min(box1[:, None, :2], box2[:, :2]) # [N, 2]
|
|
98
|
+
rb = torch.max(box1[:, None, 2:], box2[:, 2:]) # [N, 2]
|
|
99
|
+
wh = (rb - lt).clamp(min=0) # [N, 2]
|
|
100
|
+
area = wh[:, :, 0] * wh[:, :, 1]
|
|
101
|
+
return iou - (area - union) / area
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""
|
|
2
|
+
------------------------------------------------------------------------
|
|
3
|
+
DIETR
|
|
4
|
+
Copyright (c) 2026 Koen Botermans
|
|
5
|
+
Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
|
6
|
+
------------------------------------------------------------------------
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
coco_classes = (
|
|
10
|
+
"person",
|
|
11
|
+
"bicycle",
|
|
12
|
+
"car",
|
|
13
|
+
"motorcycle",
|
|
14
|
+
"airplane",
|
|
15
|
+
"bus",
|
|
16
|
+
"train",
|
|
17
|
+
"truck",
|
|
18
|
+
"boat",
|
|
19
|
+
"traffic light",
|
|
20
|
+
"fire hydrant",
|
|
21
|
+
"stop sign",
|
|
22
|
+
"parking meter",
|
|
23
|
+
"bench",
|
|
24
|
+
"bird",
|
|
25
|
+
"cat",
|
|
26
|
+
"dog",
|
|
27
|
+
"horse",
|
|
28
|
+
"sheep",
|
|
29
|
+
"cow",
|
|
30
|
+
"elephant",
|
|
31
|
+
"bear",
|
|
32
|
+
"zebra",
|
|
33
|
+
"giraffe",
|
|
34
|
+
"backpack",
|
|
35
|
+
"umbrella",
|
|
36
|
+
"handbag",
|
|
37
|
+
"tie",
|
|
38
|
+
"suitcase",
|
|
39
|
+
"frisbee",
|
|
40
|
+
"skis",
|
|
41
|
+
"snowboard",
|
|
42
|
+
"sports ball",
|
|
43
|
+
"kite",
|
|
44
|
+
"baseball bat",
|
|
45
|
+
"baseball glove",
|
|
46
|
+
"skateboard",
|
|
47
|
+
"surfboard",
|
|
48
|
+
"tennis racket",
|
|
49
|
+
"bottle",
|
|
50
|
+
"wine glass",
|
|
51
|
+
"cup",
|
|
52
|
+
"fork",
|
|
53
|
+
"knife",
|
|
54
|
+
"spoon",
|
|
55
|
+
"bowl",
|
|
56
|
+
"banana",
|
|
57
|
+
"apple",
|
|
58
|
+
"sandwich",
|
|
59
|
+
"orange",
|
|
60
|
+
"broccoli",
|
|
61
|
+
"carrot",
|
|
62
|
+
"hot dog",
|
|
63
|
+
"pizza",
|
|
64
|
+
"donut",
|
|
65
|
+
"cake",
|
|
66
|
+
"chair",
|
|
67
|
+
"couch",
|
|
68
|
+
"potted plant",
|
|
69
|
+
"bed",
|
|
70
|
+
"dining table",
|
|
71
|
+
"toilet",
|
|
72
|
+
"tv",
|
|
73
|
+
"laptop",
|
|
74
|
+
"mouse",
|
|
75
|
+
"remote",
|
|
76
|
+
"keyboard",
|
|
77
|
+
"cell phone",
|
|
78
|
+
"microwave",
|
|
79
|
+
"oven",
|
|
80
|
+
"toaster",
|
|
81
|
+
"sink",
|
|
82
|
+
"refrigerator",
|
|
83
|
+
"book",
|
|
84
|
+
"clock",
|
|
85
|
+
"vase",
|
|
86
|
+
"scissors",
|
|
87
|
+
"teddy bear",
|
|
88
|
+
"hair drier",
|
|
89
|
+
"toothbrush",
|
|
90
|
+
)
|
|
91
|
+
coco_categories = [
|
|
92
|
+
{"supercategory": "person", "id": 1, "name": "person"},
|
|
93
|
+
{"supercategory": "vehicle", "id": 2, "name": "bicycle"},
|
|
94
|
+
{"supercategory": "vehicle", "id": 3, "name": "car"},
|
|
95
|
+
{"supercategory": "vehicle", "id": 4, "name": "motorcycle"},
|
|
96
|
+
{"supercategory": "vehicle", "id": 5, "name": "airplane"},
|
|
97
|
+
{"supercategory": "vehicle", "id": 6, "name": "bus"},
|
|
98
|
+
{"supercategory": "vehicle", "id": 7, "name": "train"},
|
|
99
|
+
{"supercategory": "vehicle", "id": 8, "name": "truck"},
|
|
100
|
+
{"supercategory": "vehicle", "id": 9, "name": "boat"},
|
|
101
|
+
{"supercategory": "outdoor", "id": 10, "name": "traffic light"},
|
|
102
|
+
{"supercategory": "outdoor", "id": 11, "name": "fire hydrant"},
|
|
103
|
+
{"supercategory": "outdoor", "id": 13, "name": "stop sign"},
|
|
104
|
+
{"supercategory": "outdoor", "id": 14, "name": "parking meter"},
|
|
105
|
+
{"supercategory": "outdoor", "id": 15, "name": "bench"},
|
|
106
|
+
{"supercategory": "animal", "id": 16, "name": "bird"},
|
|
107
|
+
{"supercategory": "animal", "id": 17, "name": "cat"},
|
|
108
|
+
{"supercategory": "animal", "id": 18, "name": "dog"},
|
|
109
|
+
{"supercategory": "animal", "id": 19, "name": "horse"},
|
|
110
|
+
{"supercategory": "animal", "id": 20, "name": "sheep"},
|
|
111
|
+
{"supercategory": "animal", "id": 21, "name": "cow"},
|
|
112
|
+
{"supercategory": "animal", "id": 22, "name": "elephant"},
|
|
113
|
+
{"supercategory": "animal", "id": 23, "name": "bear"},
|
|
114
|
+
{"supercategory": "animal", "id": 24, "name": "zebra"},
|
|
115
|
+
{"supercategory": "animal", "id": 25, "name": "giraffe"},
|
|
116
|
+
{"supercategory": "accessory", "id": 27, "name": "backpack"},
|
|
117
|
+
{"supercategory": "accessory", "id": 28, "name": "umbrella"},
|
|
118
|
+
{"supercategory": "accessory", "id": 31, "name": "handbag"},
|
|
119
|
+
{"supercategory": "accessory", "id": 32, "name": "tie"},
|
|
120
|
+
{"supercategory": "accessory", "id": 33, "name": "suitcase"},
|
|
121
|
+
{"supercategory": "sports", "id": 34, "name": "frisbee"},
|
|
122
|
+
{"supercategory": "sports", "id": 35, "name": "skis"},
|
|
123
|
+
{"supercategory": "sports", "id": 36, "name": "snowboard"},
|
|
124
|
+
{"supercategory": "sports", "id": 37, "name": "sports ball"},
|
|
125
|
+
{"supercategory": "sports", "id": 38, "name": "kite"},
|
|
126
|
+
{"supercategory": "sports", "id": 39, "name": "baseball bat"},
|
|
127
|
+
{"supercategory": "sports", "id": 40, "name": "baseball glove"},
|
|
128
|
+
{"supercategory": "sports", "id": 41, "name": "skateboard"},
|
|
129
|
+
{"supercategory": "sports", "id": 42, "name": "surfboard"},
|
|
130
|
+
{"supercategory": "sports", "id": 43, "name": "tennis racket"},
|
|
131
|
+
{"supercategory": "kitchen", "id": 44, "name": "bottle"},
|
|
132
|
+
{"supercategory": "kitchen", "id": 46, "name": "wine glass"},
|
|
133
|
+
{"supercategory": "kitchen", "id": 47, "name": "cup"},
|
|
134
|
+
{"supercategory": "kitchen", "id": 48, "name": "fork"},
|
|
135
|
+
{"supercategory": "kitchen", "id": 49, "name": "knife"},
|
|
136
|
+
{"supercategory": "kitchen", "id": 50, "name": "spoon"},
|
|
137
|
+
{"supercategory": "kitchen", "id": 51, "name": "bowl"},
|
|
138
|
+
{"supercategory": "food", "id": 52, "name": "banana"},
|
|
139
|
+
{"supercategory": "food", "id": 53, "name": "apple"},
|
|
140
|
+
{"supercategory": "food", "id": 54, "name": "sandwich"},
|
|
141
|
+
{"supercategory": "food", "id": 55, "name": "orange"},
|
|
142
|
+
{"supercategory": "food", "id": 56, "name": "broccoli"},
|
|
143
|
+
{"supercategory": "food", "id": 57, "name": "carrot"},
|
|
144
|
+
{"supercategory": "food", "id": 58, "name": "hot dog"},
|
|
145
|
+
{"supercategory": "food", "id": 59, "name": "pizza"},
|
|
146
|
+
{"supercategory": "food", "id": 60, "name": "donut"},
|
|
147
|
+
{"supercategory": "food", "id": 61, "name": "cake"},
|
|
148
|
+
{"supercategory": "furniture", "id": 62, "name": "chair"},
|
|
149
|
+
{"supercategory": "furniture", "id": 63, "name": "couch"},
|
|
150
|
+
{"supercategory": "furniture", "id": 64, "name": "potted plant"},
|
|
151
|
+
{"supercategory": "furniture", "id": 65, "name": "bed"},
|
|
152
|
+
{"supercategory": "furniture", "id": 67, "name": "dining table"},
|
|
153
|
+
{"supercategory": "furniture", "id": 70, "name": "toilet"},
|
|
154
|
+
{"supercategory": "electronic", "id": 72, "name": "tv"},
|
|
155
|
+
{"supercategory": "electronic", "id": 73, "name": "laptop"},
|
|
156
|
+
{"supercategory": "electronic", "id": 74, "name": "mouse"},
|
|
157
|
+
{"supercategory": "electronic", "id": 75, "name": "remote"},
|
|
158
|
+
{"supercategory": "electronic", "id": 76, "name": "keyboard"},
|
|
159
|
+
{"supercategory": "electronic", "id": 77, "name": "cell phone"},
|
|
160
|
+
{"supercategory": "appliance", "id": 78, "name": "microwave"},
|
|
161
|
+
{"supercategory": "appliance", "id": 79, "name": "oven"},
|
|
162
|
+
{"supercategory": "appliance", "id": 80, "name": "toaster"},
|
|
163
|
+
{"supercategory": "appliance", "id": 81, "name": "sink"},
|
|
164
|
+
{"supercategory": "appliance", "id": 82, "name": "refrigerator"},
|
|
165
|
+
{"supercategory": "indoor", "id": 84, "name": "book"},
|
|
166
|
+
{"supercategory": "indoor", "id": 85, "name": "clock"},
|
|
167
|
+
{"supercategory": "indoor", "id": 86, "name": "vase"},
|
|
168
|
+
{"supercategory": "indoor", "id": 87, "name": "scissors"},
|
|
169
|
+
{"supercategory": "indoor", "id": 88, "name": "teddy bear"},
|
|
170
|
+
{"supercategory": "indoor", "id": 89, "name": "hair drier"},
|
|
171
|
+
{"supercategory": "indoor", "id": 90, "name": "toothbrush"},
|
|
172
|
+
]
|
|
173
|
+
coco_to_label = {
|
|
174
|
+
1: 'person',
|
|
175
|
+
2: 'bicycle',
|
|
176
|
+
3: 'car',
|
|
177
|
+
4: 'motorcycle',
|
|
178
|
+
5: 'airplane',
|
|
179
|
+
6: 'bus',
|
|
180
|
+
7: 'train',
|
|
181
|
+
8: 'truck',
|
|
182
|
+
9: 'boat',
|
|
183
|
+
10: 'traffic light',
|
|
184
|
+
11: 'fire hydrant',
|
|
185
|
+
13: 'stop sign',
|
|
186
|
+
14: 'parking meter',
|
|
187
|
+
15: 'bench',
|
|
188
|
+
16: 'bird',
|
|
189
|
+
17: 'cat',
|
|
190
|
+
18: 'dog',
|
|
191
|
+
19: 'horse',
|
|
192
|
+
20: 'sheep',
|
|
193
|
+
21: 'cow',
|
|
194
|
+
22: 'elephant',
|
|
195
|
+
23: 'bear',
|
|
196
|
+
24: 'zebra',
|
|
197
|
+
25: 'giraffe',
|
|
198
|
+
27: 'backpack',
|
|
199
|
+
28: 'umbrella',
|
|
200
|
+
31: 'handbag',
|
|
201
|
+
32: 'tie',
|
|
202
|
+
33: 'suitcase',
|
|
203
|
+
34: 'frisbee',
|
|
204
|
+
35: 'skis',
|
|
205
|
+
36: 'snowboard',
|
|
206
|
+
37: 'sports ball',
|
|
207
|
+
38: 'kite',
|
|
208
|
+
39: 'baseball bat',
|
|
209
|
+
40: 'baseball glove',
|
|
210
|
+
41: 'skateboard',
|
|
211
|
+
42: 'surfboard',
|
|
212
|
+
43: 'tennis racket',
|
|
213
|
+
44: 'bottle',
|
|
214
|
+
46: 'wine glass',
|
|
215
|
+
47: 'cup',
|
|
216
|
+
48: 'fork',
|
|
217
|
+
49: 'knife',
|
|
218
|
+
50: 'spoon',
|
|
219
|
+
51: 'bowl',
|
|
220
|
+
52: 'banana',
|
|
221
|
+
53: 'apple',
|
|
222
|
+
54: 'sandwich',
|
|
223
|
+
55: 'orange',
|
|
224
|
+
56: 'broccoli',
|
|
225
|
+
57: 'carrot',
|
|
226
|
+
58: 'hot dog',
|
|
227
|
+
59: 'pizza',
|
|
228
|
+
60: 'donut',
|
|
229
|
+
61: 'cake',
|
|
230
|
+
62: 'chair',
|
|
231
|
+
63: 'couch',
|
|
232
|
+
64: 'potted plant',
|
|
233
|
+
65: 'bed',
|
|
234
|
+
67: 'dining table',
|
|
235
|
+
70: 'toilet',
|
|
236
|
+
72: 'tv',
|
|
237
|
+
73: 'laptop',
|
|
238
|
+
74: 'mouse',
|
|
239
|
+
75: 'remote',
|
|
240
|
+
76: 'keyboard',
|
|
241
|
+
77: 'cell phone',
|
|
242
|
+
78: 'microwave',
|
|
243
|
+
79: 'oven',
|
|
244
|
+
80: 'toaster',
|
|
245
|
+
81: 'sink',
|
|
246
|
+
82: 'refrigerator',
|
|
247
|
+
84: 'book',
|
|
248
|
+
85: 'clock',
|
|
249
|
+
86: 'vase',
|
|
250
|
+
87: 'scissors',
|
|
251
|
+
88: 'teddy bear',
|
|
252
|
+
89: 'hair drier',
|
|
253
|
+
90: 'toothbrush'
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
coco_label_to_normal = {k: i for i, k in enumerate(coco_to_label.keys())}
|
|
257
|
+
normal_label_to_coco = {v: k for k, v in coco_label_to_normal.items()}
|
|
258
|
+
|
|
259
|
+
coco_result_names = [
|
|
260
|
+
"AP-0.95",
|
|
261
|
+
"AP-0.50",
|
|
262
|
+
"AP-0.75",
|
|
263
|
+
"AP-small",
|
|
264
|
+
"AP-medium",
|
|
265
|
+
"AP-large",
|
|
266
|
+
"AR-1det",
|
|
267
|
+
"AR-10det",
|
|
268
|
+
"AR-0.95",
|
|
269
|
+
"AR-small",
|
|
270
|
+
"AR-medium",
|
|
271
|
+
"AR-large",
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
mapping = {
|
|
275
|
+
"Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ]": "AP-0.95",
|
|
276
|
+
"Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ]": "AP-0.50",
|
|
277
|
+
"Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ]": "AP-0.75",
|
|
278
|
+
"Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ]": "AP-small",
|
|
279
|
+
"Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ]": "AP-medium",
|
|
280
|
+
"Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ]": "AP-large",
|
|
281
|
+
"Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ]": "AR-1det",
|
|
282
|
+
"Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ]": "AR-10det",
|
|
283
|
+
"Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ]": "AR-0.95",
|
|
284
|
+
"Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ]": "AR-small",
|
|
285
|
+
"Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ]": "AR-medium",
|
|
286
|
+
"Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ]": "AR-large",
|
|
287
|
+
}
|
dietr/data/conversion.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""
|
|
2
|
+
------------------------------------------------------------------------
|
|
3
|
+
DIETR
|
|
4
|
+
Copyright (c) 2026 Koen Botermans
|
|
5
|
+
Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
|
6
|
+
------------------------------------------------------------------------
|
|
7
|
+
"""
|
|
8
|
+
import torch
|
|
9
|
+
import numpy as np
|
|
10
|
+
from dietr.data.coco_definitions import (
|
|
11
|
+
coco_label_to_normal,
|
|
12
|
+
normal_label_to_coco,
|
|
13
|
+
coco_classes,
|
|
14
|
+
)
|
|
15
|
+
from dietr.data.msk_conversion import (
|
|
16
|
+
msk_rle_to_msk_np,
|
|
17
|
+
msk_rle_to_compressed_rle,
|
|
18
|
+
msk_polygon_to_msk_np,
|
|
19
|
+
msk_np_to_msk_crp_np,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from dietr.data.box_conversion import box_coco_to_yolo
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def inverse_sigmoid(x: torch.Tensor, eps: float = 1e-5) -> torch.Tensor:
|
|
26
|
+
x = x.clip(min=0.0, max=1.0)
|
|
27
|
+
return torch.log(x.clip(min=eps) / (1 - x).clip(min=eps))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def coco_seg_to_msk_np(coco_seg: dict, img_hw: tuple[int, int]) -> np.ndarray:
|
|
31
|
+
if not isinstance(coco_seg, dict):
|
|
32
|
+
msk_np = msk_polygon_to_msk_np(polygon=coco_seg, img_hw=img_hw)
|
|
33
|
+
else:
|
|
34
|
+
if isinstance(coco_seg["counts"], str):
|
|
35
|
+
msk_np = msk_rle_to_msk_np(rle=coco_seg)
|
|
36
|
+
else:
|
|
37
|
+
msk_np = msk_rle_to_msk_np(msk_rle_to_compressed_rle(coco_ann=coco_seg))
|
|
38
|
+
return msk_np.astype(np.bool_)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def coco_ann_to_sample_np(
|
|
42
|
+
coco_ann: list[any],
|
|
43
|
+
img_hw: tuple[int, int],
|
|
44
|
+
min_visibility: float,
|
|
45
|
+
coco_dataset: bool,
|
|
46
|
+
msk: bool,
|
|
47
|
+
) -> dict[str, np.ndarray]:
|
|
48
|
+
"""Convert anntations from the coco annotation format to the internal data format, which is just a dictionary of numpy arrays..
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
coco_ann (list[coco_annotation]): list of coco annotations.
|
|
52
|
+
img_hw (tuple[int, int]): the original height and with of the original image, this is need to scale the bounding boxes.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
sample_np (dict[str, np.ndarray]): combined targets that can be use for training.
|
|
56
|
+
|
|
57
|
+
It has the following elements:
|
|
58
|
+
box_np (np.ndarray): Boxes in normalized yolo format. (or cxcywh).
|
|
59
|
+
cls_np (np.ndarray): Labels in normal format, thus 0: person, etc...
|
|
60
|
+
msk_np (np.ndarray): Masks in np.ndarray.
|
|
61
|
+
crp_np (np.ndarray): Cropping of the masks in a numpy array, this cropping is used when computing the loss, to stabilize training the segmentation outputs.
|
|
62
|
+
"""
|
|
63
|
+
box_np = []
|
|
64
|
+
cls_np = []
|
|
65
|
+
if msk:
|
|
66
|
+
msk_np = []
|
|
67
|
+
crp_np = []
|
|
68
|
+
for annotation in coco_ann:
|
|
69
|
+
if annotation["iscrowd"] == 1:
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
box_yolo = box_coco_to_yolo(annotation["bbox"], img_hw=img_hw)
|
|
73
|
+
if (box_yolo[2] <= min_visibility) or (box_yolo[3] <= min_visibility):
|
|
74
|
+
continue
|
|
75
|
+
box_np.append(box_yolo)
|
|
76
|
+
|
|
77
|
+
if coco_dataset:
|
|
78
|
+
cls_np.append(label_coco_to_normal(annotation["category_id"]))
|
|
79
|
+
else:
|
|
80
|
+
cls_np.append(annotation["category_id"])
|
|
81
|
+
|
|
82
|
+
if msk:
|
|
83
|
+
msk_np.append(
|
|
84
|
+
coco_seg_to_msk_np(coco_seg=annotation["segmentation"], img_hw=img_hw)
|
|
85
|
+
)
|
|
86
|
+
crp_np.append(msk_np_to_msk_crp_np(msk_np=msk_np[-1]))
|
|
87
|
+
|
|
88
|
+
if len(box_np) == 0:
|
|
89
|
+
if msk:
|
|
90
|
+
return {
|
|
91
|
+
"box_np": np.array([]).reshape(-1, 4),
|
|
92
|
+
"msk_np": np.array([]).reshape(-1, 4, 4),
|
|
93
|
+
"crp_np": np.array([]).reshape(-1, 4, 4),
|
|
94
|
+
"cls_np": np.array([]),
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
"box_np": np.array([]).reshape(-1, 4),
|
|
98
|
+
"cls_np": np.array([]),
|
|
99
|
+
}
|
|
100
|
+
if msk:
|
|
101
|
+
return {
|
|
102
|
+
"box_np": np.stack(box_np),
|
|
103
|
+
"cls_np": np.stack(cls_np),
|
|
104
|
+
"msk_np": np.stack(msk_np),
|
|
105
|
+
"crp_np": np.stack(crp_np),
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
"box_np": np.stack(box_np),
|
|
109
|
+
"cls_np": np.stack(cls_np),
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def label_coco_to_normal(coco_label: int) -> int:
|
|
114
|
+
"""In the coco format the labels are from 1 to 90, this function just maps these labels to label_id,
|
|
115
|
+
with id=0, is person."""
|
|
116
|
+
return coco_label_to_normal[coco_label]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def label_normal_to_coco(normal_label: int) -> int:
|
|
120
|
+
return normal_label_to_coco[normal_label]
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def label_normal_to_name(normal_label: int) -> str:
|
|
124
|
+
return coco_classes[normal_label - 1]
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def label_coco_to_name(normal_label: int) -> str:
|
|
128
|
+
return coco_classes[label_coco_to_normal(normal_label) - 1]
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""
|
|
2
|
+
------------------------------------------------------------------------
|
|
3
|
+
DIETR
|
|
4
|
+
Copyright (c) 2026 Koen Botermans
|
|
5
|
+
Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
|
6
|
+
------------------------------------------------------------------------
|
|
7
|
+
"""
|
|
8
|
+
import torch
|
|
9
|
+
import numpy as np
|
|
10
|
+
from torch.utils.data.distributed import DistributedSampler
|
|
11
|
+
from dietr.data.trn_dataset import CocoDataset
|
|
12
|
+
from dietr.data.val_dataset import CocoValDataset
|
|
13
|
+
from dietr.data.trn_batch_collate import BatchImageCollateFunction
|
|
14
|
+
from dietr.data.val_batch_collate import ValBatchImageCollateFunction
|
|
15
|
+
|
|
16
|
+
from collections.abc import Iterator
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_val_dataloader(
|
|
22
|
+
config, multi_gpu: bool = False, tta: bool = False
|
|
23
|
+
) -> torch.utils.data.DataLoader:
|
|
24
|
+
coco_dataset = CocoValDataset(
|
|
25
|
+
coco_ann_file=config["val_ann_file"],
|
|
26
|
+
coco_img_root=config["val_img_root"],
|
|
27
|
+
img_base_size=config["val_img_base_size"],
|
|
28
|
+
)
|
|
29
|
+
batch_collate = ValBatchImageCollateFunction(
|
|
30
|
+
base_size=config["val_img_base_size"],
|
|
31
|
+
val_sizes=[config["val_img_base_size"]]
|
|
32
|
+
if not tta
|
|
33
|
+
else config["val_tta_img_sizes"],
|
|
34
|
+
)
|
|
35
|
+
return torch.utils.data.DataLoader(
|
|
36
|
+
dataset=coco_dataset,
|
|
37
|
+
batch_size=config["val_batch_size"],
|
|
38
|
+
shuffle=False,
|
|
39
|
+
collate_fn=batch_collate,
|
|
40
|
+
persistent_workers=True,
|
|
41
|
+
pin_memory=True,
|
|
42
|
+
num_workers=config["n_val_workers"],
|
|
43
|
+
sampler=DistributedSampler(coco_dataset, shuffle=False) if multi_gpu else None,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def contains_targets(y_trn_batch: dict[str, list[torch.Tensor]]) -> bool:
|
|
47
|
+
for box in y_trn_batch["box"]:
|
|
48
|
+
if len(box) == 0:
|
|
49
|
+
return False
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def cycle(iterable: Any) -> Iterator[Any]:
|
|
54
|
+
"""Create a dataloader-safe cyclical iterator.
|
|
55
|
+
From: https://github.com/pytorch/pytorch/issues/23900#issuecomment-518858050
|
|
56
|
+
"""
|
|
57
|
+
iterator = iter(iterable)
|
|
58
|
+
while True:
|
|
59
|
+
try:
|
|
60
|
+
(x_trn_batch, y_trn_batch) = next(iterator)
|
|
61
|
+
# while not contains_targets(y_trn_batch=y_trn_batch):
|
|
62
|
+
# (x_trn_batch, y_trn_batch) = next(iterator)
|
|
63
|
+
yield (x_trn_batch, y_trn_batch)
|
|
64
|
+
except StopIteration:
|
|
65
|
+
iterator = iter(iterable)
|
|
66
|
+
|
|
67
|
+
def get_trn_dataloader(config, multi_gpu: bool, cycle_dataloader: bool) -> Iterator[Any]:
|
|
68
|
+
coco_dataset = CocoDataset(
|
|
69
|
+
msk=config["msk"],
|
|
70
|
+
coco_ann_file=config["trn_ann_file"],
|
|
71
|
+
coco_img_root=config["trn_img_root"],
|
|
72
|
+
img_base_size=config["trn_img_base_size"],
|
|
73
|
+
min_visibility=config["min_visibility"],
|
|
74
|
+
td_flip_p=config["dataset_dt_flip_p"],
|
|
75
|
+
lr_flip_p=config["dataset_lr_flip_p"],
|
|
76
|
+
mask_scaling=config["mask_scaling"],
|
|
77
|
+
photo_transform_p=config["dataset_photo_transform_p"],
|
|
78
|
+
filter_empty=config["dataset_filter_empy"],
|
|
79
|
+
random_zoom_p=config["dataset_random_zoom_p"],
|
|
80
|
+
random_crop_p=config["dataset_random_crop_p"],
|
|
81
|
+
mosaic_p=config["dataset_mosaic_p"],
|
|
82
|
+
coco_dataset=config["coco_dataset"],
|
|
83
|
+
)
|
|
84
|
+
batch_collate = BatchImageCollateFunction(
|
|
85
|
+
base_size=config["trn_img_base_size"],
|
|
86
|
+
multi_scale_p=config.get("multi_scale_p", 1.0),
|
|
87
|
+
multi_input_size=config["multi_input_size"],
|
|
88
|
+
double_multi_input_size=config["double_multi_input_size"],
|
|
89
|
+
mask_scaling=config["mask_scaling"],
|
|
90
|
+
dtype=np.float32,
|
|
91
|
+
both_sides=config.get("both_sides", True),
|
|
92
|
+
)
|
|
93
|
+
dataloader = torch.utils.data.DataLoader(
|
|
94
|
+
dataset=coco_dataset,
|
|
95
|
+
batch_size=config["trn_batch_size"],
|
|
96
|
+
shuffle=not multi_gpu,
|
|
97
|
+
collate_fn=batch_collate,
|
|
98
|
+
persistent_workers=True,
|
|
99
|
+
pin_memory=True,
|
|
100
|
+
num_workers=config["n_trn_workers"],
|
|
101
|
+
sampler=DistributedSampler(coco_dataset) if multi_gpu else None,
|
|
102
|
+
)
|
|
103
|
+
if cycle_dataloader:
|
|
104
|
+
return cycle(dataloader)
|
|
105
|
+
return dataloader
|
|
106
|
+
|
|
107
|
+
|
dietr/data/loading.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
------------------------------------------------------------------------
|
|
3
|
+
DIETR
|
|
4
|
+
Copyright (c) 2026 Koen Botermans
|
|
5
|
+
Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
|
6
|
+
------------------------------------------------------------------------
|
|
7
|
+
"""
|
|
8
|
+
import os
|
|
9
|
+
import cv2
|
|
10
|
+
import pycocotools
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_coco_img_np(
|
|
15
|
+
coco_gt: pycocotools.coco.COCO, img_id: int, coco_img_path: str
|
|
16
|
+
) -> tuple[np.ndarray, tuple[int, int]]:
|
|
17
|
+
"""Given a pycocotools and img_id,"""
|
|
18
|
+
img_info = coco_gt.loadImgs(ids=[img_id])[0]
|
|
19
|
+
img_path = img_info["file_name"]
|
|
20
|
+
combined_img_path = os.path.join(coco_img_path, img_path)
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
cv2.cvtColor(cv2.imread(combined_img_path), cv2.COLOR_RGB2BGR),
|
|
24
|
+
(
|
|
25
|
+
img_info["height"],
|
|
26
|
+
img_info["width"],
|
|
27
|
+
) )
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def load_coco_ann(coco_gt: pycocotools.coco.COCO, img_id: int) -> list[any]:
|
|
31
|
+
ann_ids = coco_gt.getAnnIds(imgIds=[img_id])
|
|
32
|
+
return coco_gt.loadAnns(ann_ids)
|