Buckets:
| """Explicit DIOR-R four-class OBB benchmark, separate from historical DOTA tests.""" | |
| import copy | |
| import json | |
| import time | |
| from pathlib import Path | |
| import numpy as np | |
| import torch | |
| from evaluation.quick_eval import detection_target,detection_metrics | |
| from training.dior_extension import Extension,EXTENSION,sha | |
| from training.model_factory import ROOT | |
| EXACT={'plane':6,'bridge':3,'ship':7,'storage-tank':8} | |
| def predict(wrapper,extension,rows,*,device='cpu'): | |
| names={i:n.replace(' ','-') for i,n in wrapper.names.items()} | |
| mapping={i:EXACT[n] for i,n in names.items() if n in EXACT} | |
| predictions=[];targets=[];broad_predictions=[];broad_targets=[];invalid=0 | |
| start=time.monotonic() | |
| for row in rows: | |
| sample=extension.load(row) | |
| with torch.inference_mode():r=wrapper.predict(sample['image'][:,:,::-1].copy(),imgsz=1024,device=device,conf=.001,max_det=300,save=False,verbose=False)[0] | |
| objects=[];vehicles=[] | |
| for p,c,s in zip(r.obb.xyxyxyxy.cpu().numpy(),r.obb.cls.cpu().numpy(),r.obb.conf.cpu().numpy()): | |
| c=int(c);center=p.mean(axis=0).astype(int) | |
| if not(0<=center[0]<800 and 0<=center[1]<800) or np.all(sample['image'][center[1],center[0]]==0):invalid+=1;continue | |
| a={'confidence':float(s),'obb_polygon':p.reshape(-1).tolist()} | |
| if c in mapping:objects.append({**a,'category_id':mapping[c]}) | |
| if names[c] in {'small-vehicle','large-vehicle'}:vehicles.append({**a,'category_id':4}) | |
| provenance=row.get('evaluation_role','train_diagnostic') | |
| predictions.append({'sample_id':row['id'],'split':row['split'],'provenance':provenance,'annotations':objects}) | |
| target=detection_target(sample,provenance);target['split']=row['split'];targets.append(target) | |
| vehicle_truth=[];vehicle_ignore=[] | |
| for a in sample['ignored_annotations']: | |
| if a.get('source_original_class')=='vehicle' and not a['source_difficult'] and a['visible_fraction']>=.7 and min(a['bbox'][2:])>=2: | |
| vehicle_truth.append({**a,'category_id':4}) | |
| else:vehicle_ignore.append(a) | |
| broad_predictions.append({'sample_id':row['id'],'annotations':vehicles}) | |
| broad_targets.append({'sample_id':row['id'],'annotations':vehicle_truth,'ignored_annotations':vehicle_ignore}) | |
| return {'predictions':predictions,'targets':targets,'broad_predictions':broad_predictions,'broad_targets':broad_targets, | |
| 'invalid_center_predictions_removed':invalid,'elapsed_seconds':time.monotonic()-start} | |
| def score(pool,thresholds): | |
| metrics=detection_metrics(pool['predictions'],pool['targets'],thresholds) | |
| count=sum(len(r['annotations']) for r in pool['predictions']) | |
| metrics['raw_predictions']=count | |
| metrics['ignored_predictions_at_iou50']=count-metrics['ap']['true_positives']-metrics['ap']['false_positives'] | |
| return metrics | |
| if __name__=='__main__': | |
| from training.model_factory import configure_local_settings | |
| configure_local_settings() | |
| from ultralytics import YOLO | |
| torch.set_num_threads(4);torch.manual_seed(42) | |
| ext=Extension();rows=[r for r in ext.rows if r.get('evaluation_role')=='selection_validation'] | |
| output=ROOT/'evaluation/runs/2026-10-30-dior-baselines';output.mkdir(exist_ok=False) | |
| thresholds=json.loads((ROOT/'model/model.json').read_text())['detection_thresholds'] | |
| report={'split':'selection_validation','sample_ids':[r['id'] for r in rows], | |
| 'extension_content_sha256':ext.approval['content_sha256'],'models':{}, | |
| 'limitations':['Four exactly mapped classes only; broad vehicle metric is separate and cannot verify size-class correctness.', | |
| 'Unknown categories use conservative class-agnostic ignore polygons, which can suppress false positives.', | |
| 'Image-level duplicate screening does not establish geographic independence.','No held-out audit or original test predictions used.']} | |
| for name in ['yolo26n-obb.pt','yolo26s-obb.pt']: | |
| path=ROOT/'training/cache/checkpoints'/name | |
| pool=predict(YOLO(str(path),task='obb'),ext,rows) | |
| (output/(name+'.predictions.json')).write_text(json.dumps(pool)) | |
| report['models'][name]={'checkpoint_sha256':sha(path.read_bytes()),'metrics':score(pool,thresholds),'elapsed_seconds':pool['elapsed_seconds']} | |
| print(name,report['models'][name]['metrics']['ap']['map50_95'],flush=True) | |
| (output/'BASELINES.json').write_text(json.dumps(report,indent=2)) | |
Xet Storage Details
- Size:
- 4.44 kB
- Xet hash:
- 8b78572cf57a2cdd35c0d317b52e8ce1dcc8d07ea4ac7e99f1e6234706b01ab3
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.