YOLO学习笔记1——json标签文件转YOLO格式
一、COCO数据集——目标实例json文件内容与格式解析
本部分参照下面这篇文章,有部分补充修改~COCO数据集(目标检测任务json文件内容总结)
https://zhuanlan.zhihu.com/p/309549190?utm_id=0COCO数据集现有三种标注类型:object instances(目标实例),object keypoints(目标上的关键点),和image captions(看图说话),使用json文件存储。笔者使用的数据集是针对object instances(目标实例)的json文件。以下介绍其内容与格式。
1.1简介
COCO数据集中目标实例的json文件整体是以字典的形式来存储内容的。主要包括5个key(info、licenses、images、annotations、categories)。
{
“info”:info, # 文件数据信息
“licenses”:[licenses], # 协议信息
“images”:[image], # 图片信息
“annotations” : [annataton], # 预测框信息
“categories” : [category] # 种类信息
}
1.2每个key对应的详细内容
1.2.1 info
info
{
“year” : int, # 年份
“version” : str, # 版本
“description” : str, # 详细描述信息
“contributor” : str, # 作者
“url” : str, # 协议链接
“date_created” : datetime, # 生成日期
}
1.2.2 licenses
“licenses”:
[{
“id”: 1, # int 协议id号 在images中遵循的license即1
“name”: null, # str 协议名
“url”: null # str 协议链接
}]
1.2.3 images
“images”:
[{
“id”:0, # int 图像id,可从0开始
“file_name”: “0.jpg”, # str 文件名
“width”: 512, # int 图像的宽
“height”: 512, # int 图像的高
“date_captured”: “2020-04-14 01:45:07.508146”, # datatime 获取日期
“license”:1, # int 遵循哪个协议
“coco_url”:””, # str coco图片链接url
“flickr_url”:”” # str flick图片链接url
}]
1.2.4 annotations
“annotations”:
[{
“id”: 0, # int 图片中每个被标记物体的id编号
“image_id”: 0, # int 该物体所在图片的编号
“category_id”: 2, # int 被标记物体的类别id编号
“iscrowd”: 0, # 0 or 1 目标是否被遮盖,默认为0
“area”: 4095.9999999999986, # float 被检测物体的面积(64 * 64 = 4096) “bbox”: [542.0, 698.0, 220.0, 271.0], # [x, y, width, height] 目标检测框的坐标信息 “segmentation”: [[621, 703, 573, 744, 542, 885, 580, 945, 650, 969, 711, 883, 762, 807, 748, 741, 649, 698]] #表示多边形坐标polygon格式,
}]
“bbox”里[x, y, width, height]x, y代表的是框体的左上角的x, y的坐标值。x,y取值为segmentation里面的x最小值与y最小值,由x(y)最大值减最小值得出的宽度(高度)
“segmentation”里[x1, y1, x2, y2, x3, y3, ……,xn,yn]是以左上角坐标为起始,顺时针依次选取坐标点。
1.2.5 categories
“categories”:
[{
“id”: 1, # int 类别id编号
“name”:”rectangle”, # str 类别名字
“supercategory”:”None” # str 类别所属的父类
},
{
“id”: 2,
“name”:”circle”,
“supercategory”: “None”
}]
二、YOLO数据label格式
YOLO数据集标签格式通常为:
:目标类别
:目标框的中心坐标x
:目标框的中心坐标y
:目标框的宽度
:目标框的高度
注意!YOLO数据皆以图像宽度和高度的比例表示!!!
笔者这里的模型所需数据格式为
三、代码
运行软件:pycharm
# json文件转换为YOLO格式标签
import re
import os
import json
# json文件地址
path_json = r'R:\Python\yolov5_finished\train_quadrant_enumeration_disease.json'
# txt存储目录
path_label = r'R:\Python\yolov5_finished\teeth_data\labels\a/'
def json2txt(path_json, path_label):
s = " "
t = "\n"
j = 0
# 定义正则表达式
pattern = r'\d+'
# 读取json文件句柄,结果转为Python的dic对象
with open(path_json, 'r', encoding='utf-8') as json_doc:
js = json.load(json_doc)
# 获取图片数量信息
count_images = len(js['images'])
count = len(js['annotations'])
for i in range(count_images):
# txt文件名称“train_i.txt”
label_num = str(re.findall(pattern, js['images'][i]['file_name'])).strip("'[]")
#print(label_num)
file_name = 'train_' + label_num + '.txt'
full_path = path_label + file_name
# 在指定路径创建一个txt
f = open(full_path, 'a')
# 同一张图片中的多个标签写入同一个txt
while j + 1 < count:
if js['annotations'][j]['image_id'] == js['annotations'][j+1]['image_id']:
# 类别
category = str(js['annotations'][j]['category_id_3'])
# 图片大小
image_w = js['images'][i]['width']
image_h = js['images'][i]['height']
# 预测框大小
pre_box_w = js['annotations'][j]['bbox'][2]
pre_box_h = js['annotations'][j]['bbox'][3]
# 左上角x,y坐标值
pre_top_left_x = float(js['annotations'][j]['bbox'][0])
pre_top_left_y = float(js['annotations'][j]['bbox'][1])
# 右下角x,y坐标值
pre_bottom_right_x = float(js['annotations'][j]['bbox'][0]) + pre_box_w
pre_bottom_right_y = float(js['annotations'][j]['bbox'][1]) + pre_box_h
# 框中心x,y坐标值
pre_center_x = pre_top_left_x + pre_box_w / 2
pre_center_y = pre_top_left_y + pre_box_h / 2
# 结果归一化
center_x = str(pre_center_x / image_w)
center_y = str(pre_center_y / image_h)
top_left_x = str(pre_top_left_x / image_w)
top_left_y = str(pre_top_left_y / image_h)
bottom_right_x = str(pre_bottom_right_x / image_w)
bottom_right_y = str(pre_bottom_right_y / image_h)
box_w = str(pre_box_w / image_w)
box_h = str(pre_box_h / image_h)
# 将数据写入txt
# c_x,c_y,w,h
#f.write(category + s + center_x + s + center_y + s + box_w + s + box_h + t)
# x1,y1,x2,y2
f.write(category + s + top_left_x + s + top_left_y + s + bottom_right_x + s + bottom_right_y + t)
j += 1
else:
# 类别
category = str(js['annotations'][j]['category_id_3'])
# 图片大小
image_w = js['images'][i]['width']
image_h = js['images'][i]['height']
# 预测框大小
pre_box_w = js['annotations'][j]['bbox'][2]
pre_box_h = js['annotations'][j]['bbox'][3]
# 左上角x,y坐标值
pre_top_left_x = float(js['annotations'][j]['bbox'][0])
pre_top_left_y = float(js['annotations'][j]['bbox'][1])
# 右下角x,y坐标值
pre_bottom_right_x = float(js['annotations'][j]['bbox'][0]) + pre_box_w
pre_bottom_right_y = float(js['annotations'][j]['bbox'][1]) + pre_box_h
# 框中心x,y坐标值
pre_center_x = pre_top_left_x + pre_box_w / 2
pre_center_y = pre_top_left_y + pre_box_h / 2
# 结果归一化
center_x = str(pre_center_x / image_w)
center_y = str(pre_center_y / image_h)
top_left_x = str(pre_top_left_x / image_w)
top_left_y = str(pre_top_left_y / image_h)
bottom_right_x = str(pre_bottom_right_x / image_w)
bottom_right_y = str(pre_bottom_right_y / image_h)
box_w = str(pre_box_w / image_w)
box_h = str(pre_box_h / image_h)
# 将数据写入txt
# c_x,c_y,w,h
# f.write(category + s + center_x + s + center_y + s + box_w + s + box_h + t)
# x1,y1,x2,y2
f.write(category + s + top_left_x + s + top_left_y + s + bottom_right_x + s + bottom_right_y + t)
j += 1
break
if j + 1 == count:
# 类别
category = str(js['annotations'][j]['category_id_3'])
# 图片大小
image_w = js['images'][i]['width']
image_h = js['images'][i]['height']
# 预测框大小
pre_box_w = js['annotations'][j]['bbox'][2]
pre_box_h = js['annotations'][j]['bbox'][3]
# 左上角x,y坐标值
pre_top_left_x = float(js['annotations'][j]['bbox'][0])
pre_top_left_y = float(js['annotations'][j]['bbox'][1])
# 右下角x,y坐标值
pre_bottom_right_x = float(js['annotations'][j]['bbox'][0]) + pre_box_w
pre_bottom_right_y = float(js['annotations'][j]['bbox'][1]) + pre_box_h
# 框中心x,y坐标值
pre_center_x = pre_top_left_x + pre_box_w / 2
pre_center_y = pre_top_left_y + pre_box_h / 2
# 结果归一化
center_x = str(pre_center_x / image_w)
center_y = str(pre_center_y / image_h)
top_left_x = str(pre_top_left_x / image_w)
top_left_y = str(pre_top_left_y / image_h)
bottom_right_x = str(pre_bottom_right_x / image_w)
bottom_right_y = str(pre_bottom_right_y / image_h)
box_w = str(pre_box_w / image_w)
box_h = str(pre_box_h / image_h)
# 将数据写入txt
# c_x,c_y,w,h
# f.write(category + s + center_x + s + center_y + s + box_w + s + box_h + t)
# x1,y1,x2,y2
f.write(category + s + top_left_x + s + top_left_y + s + bottom_right_x + s + bottom_right_y + t)
# 主函数
json2txt(path_json, path_label)
四、总结
CSDN上有很多博主写的很好,我的这个代码可能效率并不是很高,仅供参考哦~
以下是我遇到的几个容易出错的地方:
1、注意json文件annotations中的bbox列表排列顺序,有可能是[x,y,h,w],这里就自取一张图片对应json文件的数据先画个框,确认之后再进行转换!
2、注意YOLO标签格式 数据之间要有空格,同时需要注意[x,y,w,h]是根据图片大小比例来换算的,所以要归一化。
3、注意每张图片的标签个数,同一张图片的标签放在一个txt里面。
本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://www.net2asp.com/33347d7405.html
