最近使用yolo进行目标检测,但是手上的数据集既不是coco也不是voc,目前paddledetection上的网络只支持这两种格式。话不多说,直接进入正题:
1.首先了解voc数据集格式
└── VOCdevkit #根目录
└── VOC2017
├── Annotations #存放xml文件,与JPEGImages中的图片一一对应,解释图片的内容等等
├── ImageSets
│ ├── Action
│ ├── Layout
│ ├── Main├── train.txt#存放文件名
│ ├── val.txt
│ └── test.txt
│ └── Segmentation
├── JPEGImages #存放源图片
├── label_list.txt#存放bbox标签
├── train.txt#JPEGImages图片路径与Annotations标签路径应
├── val.txt
└── test.txt
查看我的数据格式,我的数据标签是json文件,下面给一张截图:
2.先从简单的开始
label_list.txt直接自己手写,看你的bbox有多少个类别,直接全写上就行,我的就两类,注意前面的序号1,2是notbook自带的,别写·
3.第二步写train.txt,事实上共有两个train.txt文件,一个在ImageSets /Main/train.txt,另一个最直接在主目录下。下面直接贴代码:
import os
import json
import cv2
import random
# voc格式最后储存位置
voc_format_save_path = r'/home/aistudio/PaddleDetection/dataset/People/ImageSets/Main/train.txt'
# yolo格式的注释文件,上文有格式
yolo_format_annotation_path = r'/home/aistudio/PaddleDetection/dataset/peopledetection/train.json'
#另一个train保存路径
train_path = r'/home/aistudio/PaddleDetection/dataset/People/train.txt'
#判断文件是否存在,path为文件路径
if os.path.exists(voc_format_save_path):
#删除文件,path为文件路径
os.remove(voc_format_save_path)
if os.path.exists(train_path):
#删除文件,path为文件路径
os.remove(train_path)
# 前面都造好了基础(为了和coco一致,其实很多都用不到的),现在开始解析自己的数据
f = open(yolo_format_annotation_path,encoding='utf-8')
content = json.load(f)
file = open(voc_format_save_path,'a')
for j in range(len(content['annotations'])):
img_path=content['annotations'][j]['name']
img_name = os.path.basename(img_path)
(img_name, extension) = os.path.splitext(img_name)
img_name=img_name+'\n'
file.write(img_name)
file.close()
print('保存成功1')
file2 = open(train_path,'a')
for j in range(len(content['annotations'])):
img_path=content['annotations'][j]['name']
img_name = os.path.basename(img_path)
(img_name1, extension) = os.path.splitext(img_name)
name='JPEGImages/'+str(img_name)+' '+'Annotations/'+str(img_name1)+'.xml\n'
file2.write(name)
file2.close()
print('保存成功2')
最终保存的文件如下:
第一个train.txt,注意只有图片名,没有具体路径和后缀名
第二个train.txt,注意格式为:路径1+‘ ’+路径2\n
4.第三步生成.xml文件,贴代码:
import os, sys
import glob
from PIL import Image
import json
import cv2
import random
label_lists = []
img_lists = []
src_label_dir = '/home/aistudio/PaddleDetection/dataset/peopledetection/train.json' ###指向自己数据集的labelTxt文件夹
out_xml_dir = '/home/aistudio/PaddleDetection/dataset/People/Annotations/' ###指向voc数据集的Annotations文件夹
f = open(src_label_dir,encoding='utf-8')
content = json.load(f)
for j in range(len(content['annotations'])):
content['annotations'][j]['name'] = content['annotations'][j]['name'].lstrip('stage1').lstrip('/')
img_path = content['annotations'][j]['name']
img_name = os.path.basename(img_path)
(img_name, extension) = os.path.splitext(img_name)
# 因为需要width和height,而我得yolo文件里没有,所以我还得读图片,很烦
# 我就用opencv读取了,当然用其他库也可以
# 别把图片路径搞错了,绝对路径和相对路径分清楚!
img_path = os.path.join('/home/aistudio/',img_path)
height,width = cv2.imread(img_path).shape[:2]
# write in xml file
# os.mknod(src_xml_dir + '/' + img + '.xml')
xml_file = open((out_xml_dir + '/' + img_name + '.xml'), 'w')
xml_file.write('<annotation>\n')
xml_file.write(' <folder>VOC2007</folder>\n')
xml_file.write(' <filename>' + str(img_name) + '.jpg' + '</filename>\n') ###若准备的图片为jpg格式则将png替换为jpg
xml_file.write(' <path>' + str(img_path) + '.jpg' + '</path>\n') ###若准备的图片为jpg格式则将png替换为jpg
xml_file.write(' <size>\n')
xml_file.write(' <width>' + str(width) + '</width>\n')
xml_file.write(' <height>' + str(height) + '</height>\n')
xml_file.write(' <depth>3</depth>\n')
xml_file.write(' </size>\n')
xml_file.write(' <segmented>0</segmented>\n')
for bbox in content['annotations'][j]['annotation']:
xmin=bbox['x']
ymin=bbox['y']
xmax=bbox['x']+bbox['w']
ymax=bbox['y']+bbox['h']
gt_label = content['annotations'][j]['type']
# 我就有时候int和str不注意各种报错
xmin,ymin,xmax,ymax= int(xmin),int(ymin),int(xmax),int(ymax)
xml_file.write(' <object>\n')
xml_file.write(' <name>'+str(gt_label)+'</name>\n')
xml_file.write(' <pose>Unspecified</pose>\n')
xml_file.write(' <truncated>0</truncated>\n')
xml_file.write(' <difficult>0</difficult>\n')
xml_file.write(' <bndbox>\n')
xml_file.write(' <xmin>'+str(xmin)+'</xmin>\n')
xml_file.write(' <ymin>'+str(ymin)+'</ymin>\n')
xml_file.write(' <xmax>'+str(xmax)+'</xmax>\n')
xml_file.write(' <ymax>'+str(ymax)+'</ymax>\n')
xml_file.write(' </bndbox>\n')
xml_file.write(' </object>\n')
xml_file.write('</annotation>')
xml_file.close()
生成的xml文件如下:
5.最后一步把图片文件copy到JPEGImages文件夹下,直接使用Linux命令
cp -r /home/aistudio/train/. /home/aistudio/PaddleDetection/dataset/People/JPEGImages
6.至此,所有的文件都搞定了,可以愉快地炼丹了,祝大家早日炼成金丹。
补充说明:验证集和测试集的操作和训练集操作一样,其他文件由于本实验没用到所以未作说明