《------往期经典推荐------》
二、机器学习实战专栏【链接】,已更新31期,欢迎关注,持续更新中~~
三、深度学习【Pytorch】专栏【链接】
四、【Stable Diffusion绘画系列】专栏【链接】
五、YOLOv8改进专栏【链接】,持续更新中~~
六、YOLO性能对比专栏【链接】,持续更新中~
《------正文------》
引言
在学术界与工业界,COCO指标因其标准化和多粒度评价能力(如小目标检测AP_s、中等目标AP_m等)被广泛采纳为通用基准。文本将详细介绍如何将YOLO模型在验证集上的评估结果转成COCO格式评估结果的详细过程与步骤。
YOLO原始评估结果如下:
转换COCO格式评估结果如下:
1.YOLO转换COCO格式标签
首先我们需要将有原始验证集中的YOLO格式标签文件转为COCO需要的Json格式标签文件,转换代码如下:
# --coding:utf-8--
# 声明文件编码为utf-8
import os # 导入os模块,用于操作文件和目录
import cv2 # 导入OpenCV库,用于图像处理
import json # 导入json模块,用于处理JSON格式数据
from tqdm import tqdm # 导入tqdm模块,用于显示进度条
import argparse # 导入argparse模块,用于解析命令行参数
classes = ['Pothole'] # 定义类别列表,当前只有一个类别:'Pothole'
# 创建ArgumentParser对象,用于解析命令行参数
parser = argparse.ArgumentParser()
parser.add_argument('--image_path', default='datasets/PotholeData/val/images', type=str, help="path of images") # 图片路径,默认值为'datasets/PotholeData/val/images'
parser.add_argument('--label_path', default='datasets/PotholeData/val/labels', type=str, help="path of labels .txt") # 标签路径,默认值为'datasets/PotholeData/val/labels'
parser.add_argument('--save_path', type=str, default='datasets/PotholeData/val/val.json', help="if not split the dataset, give a path to a json file") # 保存路径,默认值为'datasets/PotholeData/val/val.json'
arg = parser.parse_args() # 解析命令行参数
def yolo2coco(arg):
print("Loading data from ", arg.image_path, arg.label_path) # 打印加载数据的路径信息
# 确保图片路径和标签路径存在
assert os.path.exists(arg.image_path), f"Image path {arg.image_path} does not exist"
assert os.path.exists(arg.label_path), f"Label path {arg.label_path} does not exist"
originImagesDir = arg.image_path # 图片路径
originLabelsDir = arg.label_path # 标签路径
# 获取图片目录下的所有文件名
indexes = os.listdir(originImagesDir)
# 初始化COCO格式的数据结构
dataset = {'categories': [], 'annotations': [], 'images': []}
# 添加类别信息到COCO格式中
for i, cls in enumerate(classes, 0):
dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'mark'})
ann_id_cnt = 0 # 初始化标注ID计数器
# 遍历图片目录中的每个文件
for k, index in enumerate(tqdm(indexes)):
txtFile = f'{index[:index.rfind(".")]}.txt' # 获取对应的标签文件名
stem = index[:index.rfind(".")] # 获取文件名(不带扩展名)
try:
im = cv2.imread(os.path.join(originImagesDir, index)) # 读取图片
height, width, _ = im.shape # 获取图片的高度、宽度
except Exception as e:
print(f'{os.path.join(originImagesDir, index)} read error.\nerror:{e}') # 如果读取失败,打印错误信息
continue # 跳过该图片
# 如果没有对应的标签文件,则跳过
if not os.path.exists(os.path.join(originLabelsDir, txtFile)):
continue
# 添加图片信息到COCO格式中
dataset['images'].append({
'file_name': index,
'id': stem,
'width': width,
'height': height
})
# 读取标签文件内容
with open(os.path.join(originLabelsDir, txtFile), 'r') as fr:
labelList = fr.readlines() # 按行读取标签内容
# 遍历标签文件中的每一行
for label in labelList:
label = label.strip().split() # 去除空格并分割字段
x = float(label[1]) # 归一化中心点x坐标
y = float(label[2]) # 归一化中心点y坐标
w = float(label[3]) # 归一化宽度
h = float(label[4]) # 归一化高度
# 将YOLO格式的(x, y, w, h)转换为COCO格式的(x1, y1, x2, y2)
H, W, _ = im.shape
x1 = (x - w / 2) * W
y1 = (y - h / 2) * H
x2 = (x + w / 2) * W
y2 = (y + h / 2) * H
# 计算实际的宽度和高度
width = max(0, x2 - x1)
height = max(0, y2 - y1)
# 添加标注信息到COCO格式中
dataset['annotations'].append({
'area': width * height, # 目标区域面积
'bbox': [x1, y1, width, height], # 边界框坐标
'category_id': int(label[0]), # 类别ID
'id': ann_id_cnt, # 标注ID
'image_id': stem, # 图片ID
'iscrowd': 0, # 是否为人群目标
'segmentation': [[x1, y1, x2, y1, x2, y2, x1, y2]] # 分割信息(矩形顶点)
})
ann_id_cnt += 1 # 更新标注ID计数器
# 将COCO格式的数据保存为JSON文件
with open(arg.save_path, 'w') as f:
json.dump(dataset, f)
print('Save annotation to {}'.format(arg.save_path))
if __name__ == "__main__":
yolo2coco(arg) # 主程序入口,调用yolo2coco函数
修改一下上述代码中的类别信息classes = ['Pothole']
,原始验证集的图片与标签路径,保存后的json文件路径。
parser.add_argument('--image_path', default='datasets/PotholeData/val/images', type=str, help="path of images")
parser.add_argument('--label_path', default='datasets/PotholeData/val/labels', type=str, help="path of labels .txt")
parser.add_argument('--save_path', type=str, default='datasets/PotholeData/val/val.json', help="if not split the dataset, give a path to a json file")
然后运行该代码,就可以生成coco格式的json标签文件。
2.生成YOLO评估结果
运行以下命令,将YOLO的评估结果保存为Json格式文件:
from ultralytics import YOLO
import matplotlib
matplotlib.use('TkAgg')
if __name__ == '__main__':
model = YOLO('models/best.pt')
model.val(data='datasets/PotholeData/data.yaml',
split='val',
save_json=True,
project='modelval'
)
运行代码后,会在modelval/val
的目录下生成predictions.json
文件,用于存储模型在验证集上预测的结果信息。
3. 生成COCO评估结果
有了上述原始标签的val.json
与预测结果信息的predictions.json
标签文件之后,我们就可以使用pycocotools
生成COCO格式的评估结果,代码如下:
注:运行前需安装pycocotools库,命令:pip install pycocotools
import argparse
from pycocotools.coco import COCO
from pycocotools.cocoeval import COCOeval
def parse_opt():
parser = argparse.ArgumentParser()
parser.add_argument('--anno_json', type=str, default='datasets/PotholeData/val/val.json', help='training model path')
parser.add_argument('--pred_json', type=str, default='modelval/val/predictions.json', help='data yaml path')
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) # 初始化标注的json文件
pred = anno.loadRes(pred_json) # 初始化预测的json文件
eval = COCOeval(anno, pred, 'bbox')
eval.evaluate()
eval.accumulate()
eval.summarize()
我们只需要将上述代码中的原始标签val.json
文件路径与预测结果的predictions.json
修改为你自己的路径,然后运行程序即可得到COCO格式的评估结果,如下图:
好了,这篇文章就介绍到这里,喜欢的小伙伴感谢给点个赞和关注,更多精彩内容持续更新~~
关于本篇文章大家有任何建议或意见,欢迎在评论区留言交流!