Karthika0308 commited on
Commit
1035f85
·
verified ·
1 Parent(s): c81bba7

Upload 3 files

Browse files
Files changed (3) hide show
  1. eval_bboxes.py +555 -0
  2. install.sh +17 -0
  3. run_inference.sh +16 -0
eval_bboxes.py ADDED
@@ -0,0 +1,555 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
2
+ import argparse
3
+ import contextlib
4
+ import copy
5
+ import io
6
+ import itertools
7
+ import json
8
+ import logging
9
+ import os
10
+ import os.path as osp
11
+ import pickle as pkl
12
+ from collections import OrderedDict
13
+
14
+ from utils.arg_parser import get_argparser
15
+ import numpy as np
16
+ import torch
17
+ from detectron2.evaluation.evaluator import DatasetEvaluator
18
+ from detectron2.evaluation.fast_eval_api import COCOeval_opt as COCOeval
19
+ from detectron2.structures import BoxMode
20
+ from detectron2.utils.logger import create_small_table
21
+ from fvcore.common.file_io import PathManager
22
+ from pycocotools.coco import COCO
23
+ from tabulate import tabulate
24
+ from torchvision.ops import box_iou
25
+
26
+
27
+ class COCOEvaluator(DatasetEvaluator):
28
+ """
29
+ Evaluate AR for object proposals, AP for instance detection/segmentation, AP
30
+ for keypoint detection outputs using COCO's metrics.
31
+ See http://cocodataset.org/#detection-eval and
32
+ http://cocodataset.org/#keypoints-eval to understand its metrics.
33
+ In addition to COCO, this evaluator is able to support any bounding box detection,
34
+ instance segmentation, or keypoint detection dataset.
35
+ """
36
+
37
+ def __init__(
38
+ self,
39
+ gt_json_file,
40
+ pred_json_file,
41
+ counting_gt_json_path,
42
+ split="val",
43
+ image_set=None,
44
+ visualize_res=True,
45
+ output_dir=None,
46
+ ):
47
+ """
48
+ Args:
49
+ dataset_name (str): name of the dataset to be evaluated.
50
+ It must have either the following corresponding metadata:
51
+ "json_file": the path to the COCO format annotation
52
+ Or it must be in detectron2's standard dataset format
53
+ so it can be converted to COCO format automatically.
54
+ cfg (CfgNode): config instance
55
+ distributed (True): if True, will collect results from all ranks and run evaluation
56
+ in the main process.
57
+ Otherwise, will evaluate the results in the current process.
58
+ output_dir (str): optional, an output directory to dump all
59
+ results predicted on the dataset. The dump contains two files:
60
+ 1. "instance_predictions.pth" a file in torch serialization
61
+ format that contains all the raw original predictions.
62
+ 2. "coco_instances_results.json" a json file in COCO's result
63
+ format.
64
+ """
65
+ self._tasks = [
66
+ "bbox",
67
+ ]
68
+ self._output_dir = output_dir
69
+ self.counting_gt_json_path = counting_gt_json_path
70
+
71
+ self._cpu_device = torch.device("cpu")
72
+
73
+ # replace fewx with d2
74
+ self._logger = logging.getLogger(__name__)
75
+
76
+ gt_json_file = PathManager.get_local_path(gt_json_file)
77
+ with contextlib.redirect_stdout(io.StringIO()):
78
+ self._coco_api = COCO(gt_json_file)
79
+
80
+ pred_json_file = PathManager.get_local_path(pred_json_file)
81
+ with contextlib.redirect_stdout(io.StringIO()):
82
+ self.pred_coco_api = COCO(pred_json_file)
83
+
84
+ with open(gt_json_file) as f:
85
+ tmp_gt = json.load(f)
86
+ info_images = tmp_gt["images"]
87
+ self.map_id_2_name = dict()
88
+ self.map_name_2_id = dict()
89
+ for info_image in info_images:
90
+ img_id = info_image["id"]
91
+ img_name = info_image["file_name"]
92
+ self.map_id_2_name[img_id] = img_name
93
+ self.map_name_2_id[img_name] = img_id
94
+
95
+ with open(counting_gt_json_path) as f:
96
+ self.point_annos = json.load(f)
97
+
98
+ # Test set json files do not contain annotations (evaluation must be
99
+ # performed using the COCO evaluation server).
100
+ self._do_evaluation = "annotations" in self._coco_api.dataset
101
+ self.counting_dict = dict()
102
+ self._predictions = []
103
+ self._image_set = image_set
104
+ self.visualize_res = visualize_res
105
+ self._vis_dir = osp.join(self._output_dir, "vis_res")
106
+ os.makedirs(self._vis_dir, exist_ok=True)
107
+ self.aps = []
108
+ self.split = split
109
+ self.relative_error = []
110
+
111
+ def _tasks_from_config(self, cfg):
112
+ """
113
+ Returns:
114
+ tuple[str]: tasks that can be evaluated under the given configuration.
115
+ """
116
+ tasks = ("bbox",)
117
+ if cfg.MODEL.MASK_ON:
118
+ tasks = tasks + ("segm",)
119
+ return tasks
120
+
121
+ def process(self):
122
+ """
123
+ Args:
124
+ inputs: the inputs to a COCO model (e.g., GeneralizedRCNN).
125
+ It is a list of dict. Each dict corresponds to an image and
126
+ contains keys like "height", "width", "file_name", "image_id".
127
+ outputs: the outputs of a COCO model. It is a list of dicts with key
128
+ "instances" that contains :class:`Instances`.
129
+ """
130
+ if self._image_set is None:
131
+ img_ids = self.pred_coco_api.getImgIds()
132
+ else:
133
+ img_ids = self._image_set
134
+ print("number of images", len(img_ids))
135
+ for img_id in img_ids:
136
+
137
+
138
+ img_name = self.map_id_2_name[img_id]
139
+ anno_ids = self.pred_coco_api.getAnnIds([img_id])
140
+ point_anno = self.point_annos[img_name]["points"]
141
+ pred_annos = self.pred_coco_api.loadAnns(anno_ids)
142
+ img_info = self.pred_coco_api.loadImgs([img_id])
143
+
144
+ prediction = {"image_id": img_id}
145
+ results = []
146
+ num_pred = len(pred_annos)
147
+ for anno in pred_annos:
148
+ box = anno["bbox"]
149
+ x_cen, y_cen, w, h = box
150
+ new_box = [x_cen, y_cen, w, h]
151
+ result = {
152
+ "image_id": anno["image_id"],
153
+ "category_id": anno["category_id"],
154
+ "bbox": new_box,
155
+ "score": anno["score"],
156
+ }
157
+
158
+ results.append(result)
159
+ num_pred = len(results)
160
+ gt_anno_ids = self._coco_api.getAnnIds([img_id])
161
+ gt_annos = self._coco_api.loadAnns(gt_anno_ids)
162
+
163
+ ap = 0
164
+
165
+ if self.visualize_res:
166
+ import cv2
167
+ img = cv2.imread(osp.join(os.path.dirname(self.counting_gt_json_path), 'images_384_VarV2', img_name))
168
+
169
+ height, width, channels = img.shape
170
+ height = 25 * len(pred_annos) + 10
171
+ score_img = np.zeros((height, width, 3), np.uint8)
172
+ score_img[:] = 255
173
+
174
+
175
+ for idx, pred_anno in enumerate(pred_annos):
176
+ pred_box = pred_anno["bbox"]
177
+
178
+ x_cen, y_cen, w, h = pred_box
179
+
180
+ pred_box = [int(x_cen), int(y_cen), int(w), int(h)]
181
+
182
+ pred_x, pred_y, pred_w, pred_h = pred_box
183
+
184
+ pred_x, pred_y, pred_w, pred_h = int(pred_x), int(pred_y), int(pred_w), int(pred_h)
185
+ img = cv2.rectangle(img, (pred_x, pred_y), (pred_x + pred_w, pred_y + pred_h), (0, 165, 255), 2)
186
+
187
+
188
+
189
+ vis_img_path = os.path.join(self._vis_dir, str(len(pred_annos)-len(gt_annos))+"_"+ img_name[:-4] + "_"+str(len(pred_annos))+".jpg")
190
+
191
+ cv2.imwrite(vis_img_path, img)
192
+
193
+ info = {
194
+ "img_name": img_name,
195
+ "img_id": img_id,
196
+ "ap": ap,
197
+ "count_gt": len(point_anno),
198
+ "count_pred": num_pred,
199
+ }
200
+ self.aps.append(info)
201
+ prediction["instances"] = results
202
+ self._predictions.append(prediction)
203
+ self.counting_dict[img_id] = {"gt": len(point_anno), "pred": num_pred}
204
+ rel_err = abs(len(point_anno) - num_pred) / len(point_anno)
205
+ self.relative_error.append(rel_err)
206
+
207
+ def evaluate(self):
208
+ predictions = self._predictions
209
+
210
+ if len(predictions) == 0:
211
+ self._logger.warning("[COCOEvaluator] Did not receive valid predictions.")
212
+ return {}
213
+
214
+ self._results = OrderedDict()
215
+ self._eval_predictions(set(self._tasks), predictions)
216
+
217
+ # Copy so the caller can do whatever with results
218
+ cnt = 0
219
+ SAE = 0 # sum of absolute errors
220
+ SSE = 0 # sum of square errors
221
+ NAE = 0
222
+ SRE = 0
223
+ preds = []
224
+ gts = []
225
+
226
+ for ii, (img_id, anno) in enumerate(self.counting_dict.items()):
227
+ gt_cnt = anno["gt"]
228
+ pred_cnt = anno["pred"]
229
+ cnt = cnt + 1
230
+ err = abs(gt_cnt - pred_cnt)
231
+
232
+ preds.append(pred_cnt)
233
+ gts.append(gt_cnt)
234
+ SAE += err
235
+ SSE += err ** 2
236
+ NAE += err / gt_cnt
237
+ SRE += err ** 2 / gt_cnt
238
+ # print("Pred cnts ", preds)
239
+ # print("gts ", gts)
240
+ # print(max(gts))
241
+ print("number of images: {}".format(cnt))
242
+ print("MAE: {:.2f}".format(SAE / cnt))
243
+ print("RMSE: {:.2f}".format((SSE / cnt) ** 0.5))
244
+ print("NAE: {:.4f}".format(NAE / cnt))
245
+ print("SRE: {:.2f}".format((SRE / cnt) ** 0.5))
246
+ print("Detect results")
247
+ print(self._results)
248
+ output_path = osp.join(self._output_dir, "each_img_infor"+self.split+".pkl")
249
+ print("save to {}".format(output_path))
250
+
251
+ with open(output_path, "wb") as handle:
252
+ pkl.dump(self.aps, handle, protocol=pkl.HIGHEST_PROTOCOL)
253
+ print(10 * "**")
254
+ return copy.deepcopy(self._results)
255
+
256
+ def _eval_predictions(self, tasks, predictions):
257
+ """
258
+ Evaluate predictions on the given tasks.
259
+ Fill self._results with the metrics of the tasks.
260
+ """
261
+ self._logger.info("Preparing results for COCO format ...")
262
+ coco_results = list(itertools.chain(*[x["instances"] for x in predictions]))
263
+
264
+ if not self._do_evaluation:
265
+ self._logger.info("Annotations are not available for evaluation.")
266
+ return
267
+
268
+ self._logger.info("Evaluating predictions ...")
269
+ for task in sorted(tasks):
270
+ if self._image_set is not None:
271
+ coco_eval = (
272
+ _evaluate_predictions_on_coco(self._coco_api, coco_results, task, self._image_set)
273
+ if len(coco_results) > 0
274
+ else None # cocoapi does not handle empty results very well
275
+ )
276
+ else:
277
+ coco_eval = (
278
+ _evaluate_predictions_on_coco(self._coco_api, coco_results, task,)
279
+ if len(coco_results) > 0
280
+ else None # cocoapi does not handle empty results very well
281
+ )
282
+
283
+ res = self._derive_coco_results(
284
+ # coco_eval, task, class_names=self._metadata.get("thing_classes")
285
+ coco_eval,
286
+ task,
287
+ class_names=["fg",],
288
+ )
289
+ self._results[task] = res
290
+
291
+ def _derive_coco_results(self, coco_eval, iou_type, class_names=None):
292
+ """
293
+ Derive the desired score numbers from summarized COCOeval.
294
+ Args:
295
+ coco_eval (None or COCOEval): None represents no predictions from model.
296
+ iou_type (str):
297
+ class_names (None or list[str]): if provided, will use it to predict
298
+ per-category AP.
299
+ Returns:
300
+ a dict of {metric name: score}
301
+ """
302
+
303
+ metrics = {"bbox": ["AP", "AP50", "AP75", "APs", "APm", "APl"],}[iou_type]
304
+
305
+ if coco_eval is None:
306
+ self._logger.warn("No predictions from the model!")
307
+ return {metric: float("nan") for metric in metrics}
308
+
309
+ # the standard metrics
310
+ results = {
311
+ metric: float(coco_eval.stats[idx] * 100 if coco_eval.stats[idx] >= 0 else "nan")
312
+ for idx, metric in enumerate(metrics)
313
+ }
314
+ self._logger.info("Evaluation results for {}: \n".format(iou_type) + create_small_table(results))
315
+ if not np.isfinite(sum(results.values())):
316
+ self._logger.info("Some metrics cannot be computed and is shown as NaN.")
317
+ if class_names is None or len(class_names) <= 1:
318
+ return results
319
+
320
+ # Compute per-category AP
321
+ # from https://github.com/facebookresearch/Detectron/blob/a6a835f5b8208c45d0dce217ce9bbda915f44df7/detectron/datasets/json_dataset_evaluator.py#L222-L252 # noqa
322
+
323
+ precisions = coco_eval.eval["precision"]
324
+ # precision has dims (iou, recall, cls, area range, max dets)
325
+ assert len(class_names) == precisions.shape[2]
326
+
327
+ results_per_category = []
328
+ for idx, name in enumerate(class_names):
329
+ # area range index 0: all area ranges
330
+ # max dets index -1: typically 100 per image
331
+ precision = precisions[:, :, idx, 0, -1]
332
+ precision = precision[precision > -1]
333
+ ap = np.mean(precision) if precision.size else float("nan")
334
+ results_per_category.append(("{}".format(name), float(ap * 100)))
335
+
336
+ # tabulate it
337
+ N_COLS = min(6, len(results_per_category) * 2)
338
+ results_flatten = list(itertools.chain(*results_per_category))
339
+ results_2d = itertools.zip_longest(*[results_flatten[i::N_COLS] for i in range(N_COLS)])
340
+ table = tabulate(
341
+ results_2d, tablefmt="pipe", floatfmt=".3f", headers=["category", "AP"] * (N_COLS // 2), numalign="left",
342
+ )
343
+ self._logger.info("Per-category {} AP: \n".format(iou_type) + table)
344
+
345
+ results.update({"AP-" + name: ap for name, ap in results_per_category})
346
+ return results
347
+
348
+
349
+ def instances_to_coco_json(instances, img_id):
350
+ """
351
+ Dump an "Instances" object to a COCO-format json that's used for evaluation.
352
+ Args:
353
+ instances (Instances):
354
+ img_id (int): the image id
355
+ Returns:
356
+ list[dict]: list of json annotations in COCO format.
357
+ """
358
+ num_instance = len(instances)
359
+ if num_instance == 0:
360
+ return []
361
+
362
+ boxes = instances.pred_boxes.tensor.numpy()
363
+ boxes = BoxMode.convert(boxes, BoxMode.XYXY_ABS, BoxMode.XYWH_ABS)
364
+ boxes = boxes.tolist()
365
+ scores = instances.scores.tolist()
366
+ classes = instances.pred_classes.tolist()
367
+
368
+ results = []
369
+ for k in range(num_instance):
370
+ result = {
371
+ "image_id": img_id,
372
+ "category_id": classes[k],
373
+ "bbox": boxes[k],
374
+ "score": scores[k],
375
+ }
376
+ results.append(result)
377
+ return results
378
+
379
+
380
+ class COCOevalMaxDets(COCOeval):
381
+ """
382
+ Modified version of COCOeval for evaluating AP with a custom
383
+ maxDets (by default for COCO, maxDets is 100)
384
+ """
385
+
386
+ def summarize(self):
387
+ """
388
+ Compute and display summary metrics for evaluation results given
389
+ a custom value for max_dets_per_image
390
+ """
391
+
392
+ def _summarize(ap=1, iouThr=None, areaRng="all", maxDets=100000):
393
+ p = self.params
394
+ iStr = " {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}"
395
+ titleStr = "Average Precision" if ap == 1 else "Average Recall"
396
+ typeStr = "(AP)" if ap == 1 else "(AR)"
397
+ iouStr = (
398
+ "{:0.2f}:{:0.2f}".format(p.iouThrs[0], p.iouThrs[-1]) if iouThr is None else "{:0.2f}".format(iouThr)
399
+ )
400
+ aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng]
401
+ mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets]
402
+ if ap == 1:
403
+ # dimension of precision: [TxRxKxAxM]
404
+ s = self.eval["precision"]
405
+ # IoU
406
+ if iouThr is not None:
407
+ t = np.where(iouThr == p.iouThrs)[0]
408
+ s = s[t]
409
+ s = s[:, :, :, aind, mind]
410
+ else:
411
+ # dimension of recall: [TxKxAxM]
412
+ s = self.eval["recall"]
413
+ if iouThr is not None:
414
+ t = np.where(iouThr == p.iouThrs)[0]
415
+ s = s[t]
416
+ s = s[:, :, aind, mind]
417
+ if len(s[s > -1]) == 0:
418
+ mean_s = -1
419
+ else:
420
+ mean_s = np.mean(s[s > -1])
421
+ print(iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s))
422
+ return mean_s
423
+
424
+ def _summarizeDets():
425
+ stats = np.zeros((12,))
426
+ # Evaluate AP using the custom limit on maximum detections per image
427
+ stats[0] = _summarize(1, maxDets=self.params.maxDets[2])
428
+ stats[1] = _summarize(1, iouThr=0.5, maxDets=self.params.maxDets[2])
429
+ stats[2] = _summarize(1, iouThr=0.75, maxDets=self.params.maxDets[2])
430
+ stats[3] = _summarize(1, areaRng="small", maxDets=self.params.maxDets[2])
431
+ stats[4] = _summarize(1, areaRng="medium", maxDets=self.params.maxDets[2])
432
+ stats[5] = _summarize(1, areaRng="large", maxDets=self.params.maxDets[2])
433
+ stats[6] = _summarize(0, maxDets=self.params.maxDets[0])
434
+ stats[7] = _summarize(0, maxDets=self.params.maxDets[1])
435
+ stats[8] = _summarize(0, maxDets=self.params.maxDets[2])
436
+ stats[9] = _summarize(0, areaRng="small", maxDets=self.params.maxDets[2])
437
+ stats[10] = _summarize(0, areaRng="medium", maxDets=self.params.maxDets[2])
438
+ stats[11] = _summarize(0, areaRng="large", maxDets=self.params.maxDets[2])
439
+ return stats
440
+
441
+ def _summarizeKps():
442
+ stats = np.zeros((10,))
443
+ stats[0] = _summarize(1, maxDets=3000)
444
+ stats[1] = _summarize(1, maxDets=3000, iouThr=0.5)
445
+ stats[2] = _summarize(1, maxDets=3000, iouThr=0.75)
446
+ stats[3] = _summarize(1, maxDets=3000, areaRng="medium")
447
+ stats[4] = _summarize(1, maxDets=3000, areaRng="large")
448
+ stats[5] = _summarize(0, maxDets=3000)
449
+ stats[6] = _summarize(0, maxDets=3000, iouThr=0.5)
450
+ stats[7] = _summarize(0, maxDets=3000, iouThr=0.75)
451
+ stats[8] = _summarize(0, maxDets=3000, areaRng="medium")
452
+ stats[9] = _summarize(0, maxDets=3000, areaRng="large")
453
+ return stats
454
+
455
+ if not self.eval:
456
+ raise Exception("Please run accumulate() first")
457
+ iouType = self.params.iouType
458
+ if iouType == "segm" or iouType == "bbox":
459
+ summarize = _summarizeDets
460
+ elif iouType == "keypoints":
461
+ summarize = _summarizeKps
462
+ self.stats = summarize()
463
+
464
+ def __str__(self):
465
+ self.summarize()
466
+
467
+
468
+ def _evaluate_predictions_on_coco(
469
+ coco_gt, coco_results, iou_type, img_ids=None, max_dets_per_image=None, kpt_oks_sigmas=None
470
+ ):
471
+ """
472
+ Evaluate the coco results using COCOEval API.
473
+ """
474
+ assert len(coco_results) > 0
475
+ coco_dt = coco_gt.loadRes(coco_results)
476
+ # coco_eval = COCOeval(coco_gt, coco_dt, iou_type)
477
+ coco_eval = COCOevalMaxDets(coco_gt, coco_dt, iou_type)
478
+ if iou_type == "segm":
479
+ coco_results = copy.deepcopy(coco_results)
480
+ # When evaluating mask AP, if the results contain bbox, cocoapi will
481
+ # use the box area as the area of the instance, instead of the mask area.
482
+ # This leads to a different definition of small/medium/large.
483
+ # We remove the bbox field to let mask AP use mask area.
484
+ for c in coco_results:
485
+ c.pop("bbox", None)
486
+
487
+ # For COCO, the default max_dets_per_image is [1, 10, 100].
488
+ if max_dets_per_image is None:
489
+ max_dets_per_image = [10000, 10000, 10000]
490
+ else:
491
+ assert (
492
+ len(max_dets_per_image) >= 3
493
+ ), "COCOeval requires maxDets (and max_dets_per_image) to have length at least 3"
494
+ # In the case that user supplies a custom input for max_dets_per_image,
495
+ # apply COCOevalMaxDets to evaluate AP with the custom input.
496
+ if max_dets_per_image[2] != 100:
497
+ coco_eval = COCOevalMaxDets(coco_gt, coco_dt, iou_type)
498
+ if iou_type != "keypoints":
499
+ coco_eval.params.maxDets = max_dets_per_image
500
+
501
+ if img_ids is not None:
502
+ coco_eval.params.imgIds = img_ids
503
+
504
+ coco_eval.evaluate()
505
+ coco_eval.accumulate()
506
+ coco_eval.summarize()
507
+
508
+ return coco_eval
509
+
510
+
511
+ def get_args_parser():
512
+ parser = argparse.ArgumentParser("GECO2", add_help=False)
513
+ parser.add_argument("--input_folder", required=True, type=str)
514
+ args = parser.parse_args()
515
+ return args
516
+
517
+
518
+ if __name__ == '__main__':
519
+ parser = argparse.ArgumentParser('GeCo', parents=[get_argparser()])
520
+ args = parser.parse_args()
521
+
522
+ input_folder = ''
523
+ dataset_folder = args.data_path
524
+ print("Evaluating on validation set")
525
+ gt_json_path = dataset_folder+"/annotations/instances_val.json"
526
+
527
+ pred_json_path = 'geco2_val.json'
528
+ counting_json_path = dataset_folder+"/annotation_FSC147_384.json"
529
+ output_dir = input_folder
530
+ coco_evaluator = COCOEvaluator(
531
+ gt_json_file=gt_json_path,
532
+ pred_json_file=pred_json_path,
533
+ counting_gt_json_path=counting_json_path,
534
+ output_dir=output_dir,
535
+ visualize_res=False,
536
+ split="val",
537
+ )
538
+ coco_evaluator.process()
539
+ coco_evaluator.evaluate()
540
+
541
+ print("Evaluating on test set")
542
+ gt_json_path = dataset_folder+"/annotations/instances_test.json"
543
+ pred_json_path = 'geco2_test.json'
544
+ counting_json_path = dataset_folder+"/annotation_FSC147_384.json"
545
+ output_dir = input_folder
546
+ coco_evaluator = COCOEvaluator(
547
+ gt_json_file=gt_json_path,
548
+ pred_json_file=pred_json_path,
549
+ counting_gt_json_path=counting_json_path,
550
+ output_dir=output_dir,
551
+ visualize_res=False,
552
+ split="test",
553
+ )
554
+ coco_evaluator.process()
555
+ coco_evaluator.evaluate()
install.sh ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ conda create -n test_geco2 python=3.10 -y
4
+ pip install torch==2.7.1 torchvision==0.22.1 torchaudio==2.7.1 --index-url https://download.pytorch.org/whl/cu126
5
+ cd ./Deformable-DETR/models/ops
6
+ CUDA_VISIBLE_DEVICES=0 python -m pip install .
7
+ cd ../../..
8
+ cp -r ./Deformable-DETR/models/ops ./models/ops
9
+ pip install hydra-core
10
+ pip install scikit-image
11
+ pip install pycocotools
12
+ pip install einops
13
+ pip install "numpy<2"
14
+ pip install gradio
15
+ pip install gradio_image_prompter
16
+ pip install huggingface-hub==0.34.3
17
+ pip install --force-reinstall "pydantic<2.11"
run_inference.sh ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ conda activate cnt2
4
+
5
+ python inference.py \
6
+ --model_name GECO2FSCD \
7
+ --data_path /d/hpc/projects/FRI/pelhanj/fsc147 \
8
+ --model_path /d/hpc/projects/FRI/pelhanj/CNT_SAM2/models/ \
9
+ --backbone resnet50 \
10
+ --reduction 16 \
11
+ --image_size 1024 \
12
+ --emb_dim 256 \
13
+ --num_heads 8 \
14
+ --kernel_dim 1 \
15
+ --num_objects 3 \
16
+ --batch_size 2 \