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