Skip to content

Commit 6c122a2

Browse files
authored
Add files via upload
1 parent efcfb42 commit 6c122a2

8 files changed

+1620
-0
lines changed

coco_eval.py

+191
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import copy
2+
import io
3+
from contextlib import redirect_stdout
4+
5+
import numpy as np
6+
import pycocotools.mask as mask_util
7+
import torch
8+
import utils
9+
from pycocotools.coco import COCO
10+
from pycocotools.cocoeval import COCOeval
11+
12+
13+
class CocoEvaluator:
14+
def __init__(self, coco_gt, iou_types):
15+
assert isinstance(iou_types, (list, tuple))
16+
coco_gt = copy.deepcopy(coco_gt)
17+
self.coco_gt = coco_gt
18+
19+
self.iou_types = iou_types
20+
self.coco_eval = {}
21+
for iou_type in iou_types:
22+
self.coco_eval[iou_type] = COCOeval(coco_gt, iouType=iou_type)
23+
24+
self.img_ids = []
25+
self.eval_imgs = {k: [] for k in iou_types}
26+
27+
def update(self, predictions):
28+
img_ids = list(np.unique(list(predictions.keys())))
29+
self.img_ids.extend(img_ids)
30+
31+
for iou_type in self.iou_types:
32+
results = self.prepare(predictions, iou_type)
33+
with redirect_stdout(io.StringIO()):
34+
coco_dt = COCO.loadRes(self.coco_gt, results) if results else COCO()
35+
coco_eval = self.coco_eval[iou_type]
36+
37+
coco_eval.cocoDt = coco_dt
38+
coco_eval.params.imgIds = list(img_ids)
39+
img_ids, eval_imgs = evaluate(coco_eval)
40+
41+
self.eval_imgs[iou_type].append(eval_imgs)
42+
43+
def synchronize_between_processes(self):
44+
for iou_type in self.iou_types:
45+
self.eval_imgs[iou_type] = np.concatenate(self.eval_imgs[iou_type], 2)
46+
create_common_coco_eval(self.coco_eval[iou_type], self.img_ids, self.eval_imgs[iou_type])
47+
48+
def accumulate(self):
49+
for coco_eval in self.coco_eval.values():
50+
coco_eval.accumulate()
51+
52+
def summarize(self):
53+
for iou_type, coco_eval in self.coco_eval.items():
54+
print(f"IoU metric: {iou_type}")
55+
coco_eval.summarize()
56+
57+
def prepare(self, predictions, iou_type):
58+
if iou_type == "bbox":
59+
return self.prepare_for_coco_detection(predictions)
60+
if iou_type == "segm":
61+
return self.prepare_for_coco_segmentation(predictions)
62+
if iou_type == "keypoints":
63+
return self.prepare_for_coco_keypoint(predictions)
64+
raise ValueError(f"Unknown iou type {iou_type}")
65+
66+
def prepare_for_coco_detection(self, predictions):
67+
coco_results = []
68+
for original_id, prediction in predictions.items():
69+
if len(prediction) == 0:
70+
continue
71+
72+
boxes = prediction["boxes"]
73+
boxes = convert_to_xywh(boxes).tolist()
74+
scores = prediction["scores"].tolist()
75+
labels = prediction["labels"].tolist()
76+
77+
coco_results.extend(
78+
[
79+
{
80+
"image_id": original_id,
81+
"category_id": labels[k],
82+
"bbox": box,
83+
"score": scores[k],
84+
}
85+
for k, box in enumerate(boxes)
86+
]
87+
)
88+
return coco_results
89+
90+
def prepare_for_coco_segmentation(self, predictions):
91+
coco_results = []
92+
for original_id, prediction in predictions.items():
93+
if len(prediction) == 0:
94+
continue
95+
96+
scores = prediction["scores"]
97+
labels = prediction["labels"]
98+
masks = prediction["masks"]
99+
100+
masks = masks > 0.5
101+
102+
scores = prediction["scores"].tolist()
103+
labels = prediction["labels"].tolist()
104+
105+
rles = [
106+
mask_util.encode(np.array(mask[0, :, :, np.newaxis], dtype=np.uint8, order="F"))[0] for mask in masks
107+
]
108+
for rle in rles:
109+
rle["counts"] = rle["counts"].decode("utf-8")
110+
111+
coco_results.extend(
112+
[
113+
{
114+
"image_id": original_id,
115+
"category_id": labels[k],
116+
"segmentation": rle,
117+
"score": scores[k],
118+
}
119+
for k, rle in enumerate(rles)
120+
]
121+
)
122+
return coco_results
123+
124+
def prepare_for_coco_keypoint(self, predictions):
125+
coco_results = []
126+
for original_id, prediction in predictions.items():
127+
if len(prediction) == 0:
128+
continue
129+
130+
boxes = prediction["boxes"]
131+
boxes = convert_to_xywh(boxes).tolist()
132+
scores = prediction["scores"].tolist()
133+
labels = prediction["labels"].tolist()
134+
keypoints = prediction["keypoints"]
135+
keypoints = keypoints.flatten(start_dim=1).tolist()
136+
137+
coco_results.extend(
138+
[
139+
{
140+
"image_id": original_id,
141+
"category_id": labels[k],
142+
"keypoints": keypoint,
143+
"score": scores[k],
144+
}
145+
for k, keypoint in enumerate(keypoints)
146+
]
147+
)
148+
return coco_results
149+
150+
151+
def convert_to_xywh(boxes):
152+
xmin, ymin, xmax, ymax = boxes.unbind(1)
153+
return torch.stack((xmin, ymin, xmax - xmin, ymax - ymin), dim=1)
154+
155+
156+
def merge(img_ids, eval_imgs):
157+
all_img_ids = utils.all_gather(img_ids)
158+
all_eval_imgs = utils.all_gather(eval_imgs)
159+
160+
merged_img_ids = []
161+
for p in all_img_ids:
162+
merged_img_ids.extend(p)
163+
164+
merged_eval_imgs = []
165+
for p in all_eval_imgs:
166+
merged_eval_imgs.append(p)
167+
168+
merged_img_ids = np.array(merged_img_ids)
169+
merged_eval_imgs = np.concatenate(merged_eval_imgs, 2)
170+
171+
# keep only unique (and in sorted order) images
172+
merged_img_ids, idx = np.unique(merged_img_ids, return_index=True)
173+
merged_eval_imgs = merged_eval_imgs[..., idx]
174+
175+
return merged_img_ids, merged_eval_imgs
176+
177+
178+
def create_common_coco_eval(coco_eval, img_ids, eval_imgs):
179+
img_ids, eval_imgs = merge(img_ids, eval_imgs)
180+
img_ids = list(img_ids)
181+
eval_imgs = list(eval_imgs.flatten())
182+
183+
coco_eval.evalImgs = eval_imgs
184+
coco_eval.params.imgIds = img_ids
185+
coco_eval._paramsEval = copy.deepcopy(coco_eval.params)
186+
187+
188+
def evaluate(imgs):
189+
with redirect_stdout(io.StringIO()):
190+
imgs.evaluate()
191+
return imgs.params.imgIds, np.asarray(imgs.evalImgs).reshape(-1, len(imgs.params.areaRng), len(imgs.params.imgIds))

0 commit comments

Comments
 (0)