| import torch |
| from torch.utils.data import DataLoader |
| from tqdm import tqdm |
| from pycocotools.cocoeval import COCOeval |
|
|
| def collate_fn(batch): |
| |
| images = [x[0] for x in batch] |
| return images |
|
|
| def ssd_coco_evaluate( |
| predictor, |
| dataset, |
| class_names, |
| iou_threshold=0.5, |
| ): |
| """ |
| Core SSD COCO evaluation loop. |
| |
| - predictor: SSD predictor object with .batch_predict(images) -> list of (boxes, labels, probs) |
| - dataset: CocoDataset (or compatible) |
| - class_names: list of class names (not directly used by COCOeval but kept for consistency) |
| - iou_threshold: used potentially for custom logic, but standard COCOeval calculates over range 0.5:0.95 |
| """ |
| |
| |
| data_loader = DataLoader( |
| dataset, |
| batch_size=32, |
| num_workers=4, |
| shuffle=False, |
| collate_fn=collate_fn |
| ) |
| |
| results = [] |
| print("Starting batched evaluation...") |
| |
| global_idx = 0 |
| |
| for batch_images in tqdm(data_loader, desc="Evaluating"): |
| batch_size = len(batch_images) |
| |
| batch_results = predictor.batch_predict(batch_images) |
| |
| for j, (boxes, labels, probs) in enumerate(batch_results): |
| dataset_index = global_idx + j |
| image_id = dataset.ids[dataset_index] |
| |
| boxes = boxes.cpu().numpy() |
| labels = labels.cpu().numpy() |
| probs = probs.cpu().numpy() |
| |
| for k in range(len(boxes)): |
| label = labels[k] |
| score = float(probs[k]) |
| box = boxes[k] |
| |
| |
| if score < 0.05: |
| continue |
| |
| |
| |
| if label == 0: |
| continue |
| |
| category_id = dataset.continuous_id_to_coco_id[label] |
| |
| x1, y1, x2, y2 = box |
| w = x2 - x1 |
| h = y2 - y1 |
| |
| results.append({ |
| "image_id": image_id, |
| "category_id": category_id, |
| "bbox": [float(x1), float(y1), float(w), float(h)], |
| "score": score |
| }) |
| |
| global_idx += batch_size |
|
|
| if len(results) == 0: |
| print("No detections found!") |
| |
| return {"mAP": 0.0} |
|
|
| |
| print("Accumulating results for COCO...") |
| coco_dt = dataset.coco.loadRes(results) |
| |
| |
| coco_eval = COCOeval(dataset.coco, coco_dt, 'bbox') |
| |
| |
| |
|
|
| coco_eval.evaluate() |
| coco_eval.accumulate() |
| coco_eval.summarize() |
| |
| |
| mAP = coco_eval.stats[0] |
| |
| return { |
| "mAP": mAP, |
| "coco_eval_object": coco_eval |
| } |
|
|