目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现

目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现

Reference:https://blog.csdn.net/qq_39686950/article/details/119153685

前言
正好自己做目标检测任务更换模型需要使用不同格式的标注文件,所以在网上找了半天类似博文,发现大多都只有代码或者解释不全,对新手不够友好,我在转换的过程中就debug了半天才转换成功,所以写下这篇博文以求尽可能的全面的解释转换过程,让其他同学少走弯路。
1.yolo v5格式(txt)
yolo v5的标注文件格式比较简单,如下图所示:

目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现
每一张图片对应一个.txt文件,每一行表示该图片的一个标注框,该图片有多少标注框就有多少行数据,每一行有五列,分别表示:类别代号、标注框横向的相对中心坐标x_center、标注框纵向的相对中心坐标y_center、标注框相对宽度w、标注框相对高度h。注意x_center、y_center、w、h为真实像素值除以图片的高和宽之后的值。
2.coco格式(json)
本文所描述的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='D:\\yolov5\\CCTSDB-2021\\train\\'
yolo_format_classes_path='D:\\yolov5\\CCTSDB-2021\\names.txt'
yolo_format_annotation_path='D:\\yolov5\\CCTSDB-2021\\labels\\train\\'
img_pathDir='D:\\yolov5\\CCTSDB-2021\\images\\train\\'

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': 2022, 'contributor': '纯粹ss', 'date_created': '2022-07-8'}
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']='2022-07-8'
    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[:5]+'.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)

重点
重点
重点
代码中你可能存在疑问的地方

coco_format_save_path='D:\\yolov5\\CCTSDB-2021\\train\\'
yolo_format_classes_path='D:\\yolov5\\CCTSDB-2021\\names.txt'
yolo_format_annotation_path='D:\\yolov5\\CCTSDB-2021\\labels\\train\\'
img_pathDir='D:\\yolov5\CCTSDB-2021\\images\\train\\'

1#coco_format_save_path 这里是你自己设置的一个路径,像我在存放yolo数据集和标签的路径下新建了两个文件夹train和val来存放新生成的coco(json)格式文件,因为我的images和labels文件夹下有两个文件分别是存放训练集和验证集的图片,第一轮运行代码的时候coco_format_save_path,yolo_format_classes_path,img_pathDir路径最后都写train,这样生成的训练集的json文件就存放在新建文件夹train里,第二轮运行之前路径最后都改成val,这样生成的验证集的json文件就存放在新建文件夹val里了。

目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现
2#yolo_format_classes_path这里用txt文件写就行, 这里是要你自己新建一个txt写的,因为之前没有,形式要写成一行一类,不知道的可以看着图片与对应的labels对照一下,要按照顺序写。我下面放个图看起来就会明白了。
目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现
txtFile=imageFile[:5]+'.txt'

这里 txtFile读取的是你的图片名字,像我的图片名字使用数字表示如图

目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现
我标签名字也是用对应的数字表示如图
目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现
我读的时候单独打印了一下, imageFile打印出来是图片名字加图片格式比如 15454.jpg,而这一行代码是要将图片名与标签对应上,所以需要去掉 .jpg加上标签的格式 .txt所以 imageFile[:5]这里的索引要你自己设置,你只需要要取你图片的名字而不能加上格式,像我的数据集就是 [:5]正好取到 15454.

好了大概需要注意的地方就是这些了,都是一些可能会有疑问以及容易出错的地方,希望能给与需要的人一些帮助。
对你有帮助的话还请点赞收藏哦嘻嘻

总结
以上就是我对目标检测中yolo v5格式和coco格式的理解和代码实现,大家如果有更深层的理解和更好的代码实现可以留言或私信讨论哦。

Original: https://blog.csdn.net/qq_45294476/article/details/125685035
Author: 纯粹ss
Title: 目标检测标注文件yolov5(txt)格式转coco(json)格式详解及代码实现

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/624248/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球