极简要点:
yolov5需要的数据格式为:
{类别class} {目标区域中心x点} {目标区域中心y点} {目标区域宽度w} {目标区域高度h}
例: 2 0.4169034090909091 0.73125 0.3366477272727273 0.5166666666666666
LabelImg标注出的数据为目标区域左上与右下的xy坐标,需要转一道才是yolov5需要的数据格式。
文件结构格式:
datasets
├── image
│ ├── train
│ └── val
└── label
├── train
└── val
文件夹image内的train内装训练图片,文件夹label内的train内装对应的标注。
文件名一一对应,例如在image/train内放了一张名为0001.jpg的图片,那就需要在label/train内放一份0001.txt,一份txt对应一张图片。
配置yolov5:
1)在yolov5/data/添加{自定义名字}.yaml,文件内容产考同目录下的coco128.yaml。
单纯训练的话download、test、val不需要
2)修改yolov5/train.py文件:
parser.add_argument部分的--data参数,修改为上面添加的{自定义名字}.yaml
--weights、--epochs、--batch-size、--img看自己的需求也可以修改
LabelImg标注数据转yolov5代码:
改parser.add_argument中的xml_path与txt_path相关即可
如果不想改,想直接用,文件结构如下放置运行python3 export.py即可
.
├── data(内放xml)
├── labels(输出txt)
└── export.py(就下面的代码)
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
import os
from os import getcwd
import random
import argparse
classes = ["head", "helmet", "clothes"]
def convert(size, box):
dw = 1. / (size[0])
dh = 1. / (size[1])
x = (box[0] + box[2]) / 2.0 - 1
y = (box[1] + box[3]) / 2.0 - 1
w = box[2] - box[0]
h = box[3] - box[1]
x = x * dw
y = y * dh
w = w * dw
h = h * dh
return x, y, w, h
def convert_annotation(in_path,out_path):
in_file = open('%s.xml'%(in_path),encoding='UTF-8')
out_file = open('%s.txt'%(out_path),'w')
tree = ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
cls = obj.find('name').text
if cls not in classes:
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
xmin = float(xmlbox.find('xmin').text)
ymin = float(xmlbox.find('ymin').text)
xmax = float(xmlbox.find('xmax').text)
ymax = float(xmlbox.find('ymax').text)
if xmin<0:
xmin=0
if ymin<0:
ymin=0
if xmax>w:
xmax=w
if ymax>h:
ymax=h
out = convert((w,h),(xmin,ymin,xmax,ymax))
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in out]) + '\n')
parser = argparse.ArgumentParser()
parser.add_argument('--xml_path', default='data', type=str, help='input xml label path')
parser.add_argument('--txt_path', default='labels', type=str, help='output txt label path')
xml_path = parser.parse_args().xml_path
txt_path = parser.parse_args().txt_path
xml_name = os.listdir(xml_path)
if not os.path.exists(txt_path):
os.makedirs(txt_path)
num=len(xml_name)
list_index = range(num)
for i in list_index:
convert_annotation(xml_path+'/'+xml_name[i][:-4],txt_path+'/'+xml_name[i][:-4])
(当时写代码时有参考他人代码,想起来写博客时一时间找不到了,如有侵权,私聊加索引)