前言
??目标检测数据集的标注格式通常有三种格式:pascal voc、coco、yolo。因此当我们运行开源代码使之用于目标检测时,会遇到开源代码所要求的数据集和我们目前数据集格式不同的问题,修改开源代码耗时耗力,因此通常修改我们的数据集格式使其和开源代码要求的数据集格式相同,本文主要描述如何将yolo v5格式转换为coco格式。
一、yolo v5格式和coco格式解析
1.yolo v5格式
??yolo v5的标注文件格式比较简单,如下图所示:
??每一张图片对应一个.txt文件,每一行表示该图片的一个标注框,该图片有多少标注框就有多少行数据,每一行有五列,分别表示:类别代号、标注框横向的相对中心坐标x_center、标注框纵向的相对中心坐标y_center、标注框相对宽度w、标注框相对高度h。注意x_center、y_center、w、h为真实像素值除以图片的高和宽之后的值。
2.coco格式
??本文所描述的coco格式为标准coco数据集里的object instances格式,coco的坐标信息为(xmin,ymin,w,h),(xmin,ymin)表示标注框的左上角坐标,这四个值都是绝对值,coco格式的基本信息描述如下:
{
"info": info,
"licenses": [license],
"images": [image],
"annotations": [annotation],
"categories": [category]
}
??和yolo v5标注文件不同的是,coco标注文件的格式为.json文件,且所有图片的标注信息在一个.json文件里,该json文件由上面描述的字典组成,该字典有五个key,下面将描述每个key对应value的详细信息:
info{
"year": int,
"version": str,
"description": str,
"contributor": str,
"url": str,
"date_created": datetime,
}
license{
"id": int,
"name": str,
"url": str,
}
image{
"id": int,
"width": int,
"height": int,
"file_name": str,
"license": int,
"flickr_url": str,
"coco_url": str,
"date_captured": datetime,
}
annotation{
"id": int,
"image_id": int,
"category_id": int,
"segmentation": RLE or [polygon],
"area": float,
"bbox": [x,y,width,height],
"iscrowd": 0 or 1,
}
category{
"id": int,
"name": str,
"supercategory": str,
}
??上述就是coco数据集的详细解析。
二、代码
??由第一节分析可知,yolo v5格式只有图片名称、类别、bounding box坐标信息,而coco格式的信息更丰富,而开源代码基本也只关注yolo v5格式里所提供的信息,因此我们不必过于纠结coco格式的多余信息。 详细代码及注释信息如下:
import os
import json
import cv2
import random
import time
from PIL import Image
coco_format_save_path='G:\\YOLO5\\DarkDataSet\\train\\'
yolo_format_classes_path='G:\\YOLO5\\DarkDataSet\\military_object.names'
yolo_format_annotation_path='G:\\YOLO5\\DarkDataSet\\train\\labels\\'
img_pathDir='G:\\YOLO5\\DarkDataSet\\train\\images\\'
with open(yolo_format_classes_path,'r') as fr:
lines1=fr.readlines()
categories=[]
for j,label in enumerate(lines1):
label=label.strip()
categories.append({'id':j+1,'name':label,'supercategory':'None'})
write_json_context=dict()
write_json_context['info']= {'description': '', 'url': '', 'version': '', 'year': 2021, 'contributor': '', 'date_created': '2021-07-25'}
write_json_context['licenses']=[{'id':1,'name':None,'url':None}]
write_json_context['categories']=categories
write_json_context['images']=[]
write_json_context['annotations']=[]
imageFileList=os.listdir(img_pathDir)
for i,imageFile in enumerate(imageFileList):
imagePath = os.path.join(img_pathDir,imageFile)
image = Image.open(imagePath)
W, H = image.size
img_context={}
img_context['file_name']=imageFile
img_context['height']=H
img_context['width']=W
img_context['date_captured']='2021-07-25'
img_context['id']=i
img_context['license']=1
img_context['color_url']=''
img_context['flickr_url']=''
write_json_context['images'].append(img_context)
txtFile=imageFile[:10]+'.txt'
with open(os.path.join(yolo_format_annotation_path,txtFile),'r') as fr:
lines=fr.readlines()
for j,line in enumerate(lines):
bbox_dict = {}
class_id,x,y,w,h=line.strip().split(' ')
class_id,x, y, w, h = int(class_id), float(x), float(y), float(w), float(h)
xmin=(x-w/2)*W
ymin=(y-h/2)*H
xmax=(x+w/2)*W
ymax=(y+h/2)*H
w=w*W
h=h*H
bbox_dict['id']=i*10000+j
bbox_dict['image_id']=i
bbox_dict['category_id']=class_id+1
bbox_dict['iscrowd']=0
height,width=abs(ymax-ymin),abs(xmax-xmin)
bbox_dict['area']=height*width
bbox_dict['bbox']=[xmin,ymin,w,h]
bbox_dict['segmentation']=[[xmin,ymin,xmax,ymin,xmax,ymax,xmin,ymax]]
write_json_context['annotations'].append(bbox_dict)
name = os.path.join(coco_format_save_path,"train"+ '.json')
with open(name,'w') as fw:
json.dump(write_json_context,fw,indent=2)
总结
??以上就是我对目标检测中yolo v5格式和coco格式的理解和代码实现,大家如果有更深层的理解和更好的代码实现可以留言或私信讨论哦。
|