🎍使用YOLO模型输出COCO评价指标
在val.py中设置参数,save_json=True
python
from ultralytics import YOLO
if __name__ == '__main__':
# 加载模型
model = YOLO('runs/train/exp/weights/best.pt')
# 验证模型
metrics=model.val(
val=True, # (bool) 在训练期间进行验证/测试
data = '', # 数据集位置
split='val', # (str) 用于验证的数据集拆分,例如'val'、'test'或'train'
batch=1, # (int) 每批的图像数量(-1 为自动批处理)
imgsz=640, # 输入图像的大小,可以是整数或w,h
device='', # 运行的设备,例如 cuda device=0 或 device=0,1,2,3 或 device=cpu
workers=8, # 数据加载的工作线程数(每个DDP进程)
save_json=True, # 保存结果到JSON文件, True if for coco metric
save_hybrid=False, # 保存标签的混合版本(标签 + 额外的预测)
conf=0.001, # 检测的目标置信度阈值(默认为0.25用于预测,0.001用于验证)
iou=0.6, # 非极大值抑制 (NMS) 的交并比 (IoU) 阈值
project='runs/val', # 项目名称(可选)
name='exp', # 实验名称,结果保存在'project/name'目录下(可选)
max_det=300, # 每张图像的最大检测数
half=False, # 使用半精度 (FP16)
dnn=False, # 使用OpenCV DNN进行ONNX推断
plots=True, # 在训练/验证期间保存图像
)
print(f"mAP50-95: {metrics.box.map}") # map50-95
print(f"mAP50: {metrics.box.map50}") # map50
print(f"mAP75: {metrics.box.map75}") # map75
speed_metrics = metrics.speed
total_time = sum(speed_metrics.values())
fps = 1000 / total_time
print(f"FPS: {fps}") # FPS
🎍新建 get_coco_metrics.py 将生成的prediction.json文件,使用COCO评价指标进行测试
python
import warnings
warnings.filterwarnings('ignore')
import argparse
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
from tidecv import TIDE, datasets
def parse_opt():
parser = argparse.ArgumentParser()
parser.add_argument('--anno_json', type=str, default='./test.json', help='label coco json path') # 标签json文件
parser.add_argument('--pred_json', type=str, default='runs/val/exp/predictions.json', help='pred coco json path') # 生成的 prediction.json文件
return parser.parse_known_args()[0]
if __name__ == '__main__':
opt = parse_opt()
anno_json = opt.anno_json
pred_json = opt.pred_json
anno = COCO(anno_json) # init annotations api
pred = anno.loadRes(pred_json) # init predictions api
eval = COCOeval(anno, pred, 'bbox')
eval.evaluate()
eval.accumulate()
eval.summarize()
tide = TIDE()
tide.evaluate_range(datasets.COCO(anno_json), datasets.COCOResult(pred_json), mode=TIDE.BOX)
tide.summarize()
tide.plot(out_dir='result')
⭕常见相关报错
assert set(annsImgIds) == (set(annsImgIds) & set (self.getImgIds()))
分析:生成的prediction.json(结果标签)与原来的 test.json(标签) 中 Image_id不一致,可能的出现的情况,
标签中的Image_id: 000123
结果标签Image_id: 123
可以看到图像编号中的 0 被省略,可以通过修改代码进行恢复,保持原Image_id不变
修改位置 ultralytics/models/yolo/detect/val.py --> def pred_to_json( )函数
采用 image_id = stem 即可
python
def pred_to_json(self, predn, filename):
"""Serialize YOLO predictions to COCO json format."""
stem = Path(filename).stem
# image_id = int(stem) if stem.isnumeric() else stem # 去掉 image_id 前面的0
image_id = stem # 保持原有不变的 image_id
box = ops.xyxy2xywh(predn[:, :4]) # xywh
box[:, :2] -= box[:, 2:] / 2 # xy center to top-left corner
for p, b in zip(predn.tolist(), box.tolist()):
self.jdict.append(
{
"image_id": image_id,
"category_id": self.class_map[int(p[5])]
+ (1 if self.is_lvis else 0), # index starts from 1 if it's lvis
"bbox": [round(x, 3) for x in b],
"score": round(p[4], 5),
}
)
⭕YOLOv12报错
在对YOLOv12模型训练测试时,会出现一下报错,验证的结果基本为0,主要原因是category_id的问题,

解决方案参考Github YOLOv12 Issues
新建一个 new_predictions.json,将已生成的 predictions.json中的category_id进行修改即可
python
import json
with open('./run/exp/predictions.json', 'r') as file:
data = json.load(file)
for item in data:
if 'category_id' in item:
item['category_id'] -= 1
with open('./run/exp/new_predictions.json', 'w') as file: # 新建一个 new_predictions.json文件
json.dump(data,file,indent=4)
对已经生成的 new_predictions.json COCO评价指标get_coco_metrics.py
就能得到正常的结果

完结!🚀 🚀 🚀