自制VOC数据集笔记

自制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就好了。
如果没用,参考原博,进行第三步修改。

发布了42 篇原创文章 · 获赞 16 · 访问量 2872

猜你喜欢

转载自blog.csdn.net/weixin_44412218/article/details/104332445