File size: 2,745 Bytes
a3f0ec9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | """Local HSS metric evaluation for S23DR 2026."""
import numpy as np
from typing import Dict, List, Tuple, Optional
import time
def compute_hss(pred_vertices, pred_edges, gt_vertices, gt_edges, vert_thresh=0.5, edge_thresh=0.5):
try:
from hoho2025.metric_helper import hss
t0 = time.time()
result = hss(pred_vertices, pred_edges, gt_vertices, gt_edges, vert_thresh=vert_thresh, edge_thresh=edge_thresh)
elapsed = time.time() - t0
return {'hss': float(result.hss), 'f1': float(result.f1), 'iou': float(result.iou), 'time': elapsed}
except Exception as e:
return {'hss': 0.0, 'f1': 0.0, 'iou': 0.0, 'time': 0.0, 'error': str(e)}
def compute_corner_f1(pred_vertices, gt_vertices, thresh=0.5):
from scipy.optimize import linear_sum_assignment
if len(pred_vertices) == 0 or len(gt_vertices) == 0:
return {'f1': 0.0, 'precision': 0.0, 'recall': 0.0, 'tp': 0}
diff = pred_vertices[:, None, :] - gt_vertices[None, :, :]
dists = np.sqrt((diff ** 2).sum(axis=-1))
row_ind, col_ind = linear_sum_assignment(dists)
tp = (dists[row_ind, col_ind] <= thresh).sum()
precision = tp / len(pred_vertices)
recall = tp / len(gt_vertices)
f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0
return {'f1': float(f1), 'precision': float(precision), 'recall': float(recall), 'tp': int(tp), 'num_pred': len(pred_vertices), 'num_gt': len(gt_vertices)}
def evaluate_batch(predictions, ground_truths, verbose=True):
hss_scores, f1_scores, iou_scores, times, errors = [], [], [], [], []
for i, ((pred_v, pred_e), (gt_v, gt_e)) in enumerate(zip(predictions, ground_truths)):
result = compute_hss(pred_v, pred_e, gt_v, gt_e)
hss_scores.append(result['hss'])
f1_scores.append(result['f1'])
iou_scores.append(result['iou'])
times.append(result['time'])
if 'error' in result:
errors.append((i, result['error']))
if verbose and (i + 1) % 10 == 0:
print(f" [{i+1}/{len(predictions)}] HSS={np.mean(hss_scores):.4f} F1={np.mean(f1_scores):.4f} IoU={np.mean(iou_scores):.4f}")
return {
'hss_mean': float(np.mean(hss_scores)), 'hss_std': float(np.std(hss_scores)),
'hss_median': float(np.median(hss_scores)), 'f1_mean': float(np.mean(f1_scores)),
'iou_mean': float(np.mean(iou_scores)), 'total_time': float(sum(times)),
'avg_time': float(np.mean(times)), 'num_samples': len(predictions),
'num_errors': len(errors), 'errors': errors[:10],
}
def quick_vertex_eval(pred_vertices, gt_vertices):
return compute_corner_f1(pred_vertices, gt_vertices)
|