自制VOC数据集
环境 win10 cuda10 pytorch1.0
项目地址:faster-rcnn
参考博客:https://blog.csdn.net/weixin_43380510/article/details/83004127
data文件夹格式:
---VOC2007
------Annotations
------ImagesSet
---------Main
--------trainval.txt
--------test.txt
------JPEGImages
Annotations放xml文件
JPEGImages放图片
Main中存放txt文件,里面是图片名称,不带“.jpg”
手动制作txt代码如下:
import os
path_name = r'D:\Coding\python\faster-rcnn.pytorch-pytorch-1.0\data\VOCdevkit\VOC2007\JPEGImages'
f = open('D:/Coding/python/faster-rcnn.pytorch-pytorch-1.0/data/VOCdevkit/VOC2007/ImagesSet/Main/trainval.txt', mode='w')
for item in os.listdir(path_name):
original_name = os.path.join(path_name, item)
print(item)#原始名称带.jpg
str_name=item.split('.')#分割字符
print(str_name[0])
f.write(str_name[0] + '\n')
又参考博主的github,将xml文件中的folder改名,也可根据博主的代码修改其他属性。
# coding=utf-8
import os
import os.path
import xml.dom.minidom
path = "D:\\Coding\python\\faster-rcnn.pytorch-pytorch-1.0\\data\\VOCdevkit\\VOC2007\\Annotations"
files = os.listdir(path) # 得到文件夹下所有文件名称
for xmlFile in files: # 遍历文件夹
if not os.path.isdir(xmlFile): # 判断是否是文件夹,不是文件夹才打开
#print(xmlFile)
# 将获取的xml文件名送入到dom解析
dom = xml.dom.minidom.parse(os.path.join(path, xmlFile)) # 输入xml文件具体路径
root = dom.documentElement
# 获取标签<name>以及<folder>的值
#name = root.getElementsByTagName('filename')
folder = root.getElementsByTagName('folder')
cnt=0
# 对每个xml文件的多个同样的属性值进行修改。此处将每一个<name>属性修改为plane,每一个<folder>属性修改为VOC2007
# for i in range(len(name)):
# print(name[i].firstChild.data)
# name[i].firstChild.data = 'res'+str(cnt)+'.jpg'
# #print(name[i].firstChild.data)
# cnt += 1
# # print(name[i].firstChild.data)
for i in range(len(folder)):
print(folder[i].firstChild.data)
folder[i].firstChild.data = 'VOC2007'
print(folder[i].firstChild.data)
# 将属性存储至xml文件中
with open(os.path.join(path, xmlFile), 'w') as fh:
dom.writexml(fh)
print('已写入')
遇到的一些问题及解决方案
1 自制的xml中含有中文字符,读取失败
这个问题真的很烦,一个个改又太麻烦了,我的path中含有中文,想用上面的方法批量修改,但是xml.dom.minidom.parse(os.path.join(path, xmlFile))这里会报错,也就是都都读不了,试了网上的代码都不行,干脆……我就先转成txt,进行读写,再转成xml,也是很快的,不用在意那些encode方式了(真是烦死了……
批量xml转txt,同样也可txt转xml
import os
path_name = r'D:\NEU-DET\IMAGES' # 批量修改的文件夹路径
i = 0 # 起始数字
for item in os.listdir(path_name):
original_name = os.path.join(path_name, item)
new_name = os.path.join(path_name, ('res'+str(i)+'.jpg'))
#上面一行选择自己想要的格式及命名方式
print(new_name)
os.rename(original_name, new_name) # 重命名
i += 1
txt修改,我也改了个脚本,主要把path那行删掉,把第一行改了改:
import os,sys
path_name = r'D:\Study\研一下\test' # 批量修改的txt文件夹路径
#f = open(r'D:\Coding\left.txt', mode='w')
for item in os.listdir(path_name):
original_name = os.path.join(path_name, item)
print(item)
str_name=item.split('.')
file_name=str_name[0]+'.'+str_name[1]
f = open(path_name+"\\"+item, 'r')#这个用来读取源文件
flist = f.readlines()
w= open(path_name+"\\"+item, 'w')#这个用来写新文件替换旧文件,和原文件同名可覆盖原文件
for l in flist:
if 'version' in l:
l = l.replace('<?xml version="1.0" ?><annotation>', '<annotation>')
#replace函数进行替换
#if 'path'not in l: #这里是为了删除带path那一行
w.write(l)
# f.writelines(flist)
写完后转回xml就好了……我可真是另辟蹊径的小机灵鬼哈哈哈哈哈哈哈
2 Keyerror:‘none’
这个是因为我的撒比误操作,labelImg画框框时候,灵机一动画了个"none",忘了加进class中了,我找了半天……这个可以用用上面的随便一种方式,筛选name是否都是你的class,找出错误文件,删掉就好。
3 keyerror:‘width’
删掉/faster-rcnn.pytorch/data/cache/voc_2007_trainval_gt_roidb.pkl介个就好。
4 assert(boxes[:,2]>=boxes[:,0]).all()
介个就是,画的框框太靠边了,问题不大……
参考链接
修改lib/datasets/imdb.py,append_flipped_images()函数,在一行代码为 boxes[:, 2] = widths[i] - oldx1 - 1下加入代码:
for b in range(len(boxes)):
if boxes[b][2]< boxes[b][0]:
boxes[b][0] = 0
修改lib/datasets/pascal_voc.py,_load_pascal_annotation()函数
for ix, obj in enumerate(objs):
bbox = obj.find('bndbox')
# Make pixel indexes 0-based
x1 = float(bbox.find('xmin').text)
y1 = float(bbox.find('ymin').text)
x2 = float(bbox.find('xmax').text)
y2 = float(bbox.find('ymax').text)
x1 y1 x2 y2本来都是有-1的,全部删掉-1就好了。
如果没用,参考原博,进行第三步修改。