# 创建索引
from pycocotools.coco import COCO
import os
import shutil
from tqdm import tqdm
import skimage.io as io
import matplotlib.pyplot as plt
import cv2
from PIL import Image, ImageDraw
from shutil import move
import xml.etree.ElementTree as ET
from random import shuffle
# 保存路径
savepath = "VOCData/"
img_dir = savepath + 'images/' #images 存取所有照片
anno_dir = savepath + 'Annotations/' #Annotations存取xml文件信息
datasets_list=['train2017', 'val2017']
classes_names = ['person']
# 读取COCO数据集地址 Store annotations and train2017/val2017/... in this folder
dataDir = './'
#写好模板,里面的%s与%d 后面文件输入输出流改变 -------转数据集阶段--------
headstr = """
VOC%sMy DatabaseCOCOflickrNULLNULLcompany%d%d%d0
"""
objstr = """
"""
tailstr = '''
'''
# if the dir is not exists,make it,else delete it
def mkr(path):
if os.path.exists(path):
shutil.rmtree(path)
os.mkdir(path)
else:
os.mkdir(path)
mkr(img_dir)
mkr(anno_dir)
def id2name(coco): # 生成字典 提取数据中的id,name标签的值 ---------处理数据阶段---------
classes = dict()
for cls in coco.dataset['categories']:
classes[cls['id']] = cls['name']
return classes
def write_xml(anno_path, head, objs, tail): #把提取的数据写入到相应模板的地方
f = open(anno_path, "w")
f.write(head)
for obj in objs:
f.write(objstr % (obj[0], obj[1], obj[2], obj[3], obj[4]))
f.write(tail)
def save_annotations_and_imgs(coco, dataset, filename, objs):
# eg:COCO_train2014_000000196610.jpg-->COCO_train2014_000000196610.xml
anno_path = anno_dir + filename[:-3] + 'xml'
img_path = dataDir + dataset + '/' + filename
dst_imgpath = img_dir + filename
img = cv2.imread(img_path)
if (img.shape[2] == 1):
print(filename + " not a RGB image")
return
shutil.copy(img_path, dst_imgpath)
head = headstr % (filename, img.shape[1], img.shape[0], img.shape[2])
tail = tailstr
write_xml(anno_path, head, objs, tail)
def showimg(coco, dataset, img, classes, cls_id, show=True):
global dataDir
I = Image.open('%s/%s/%s' % (dataDir, dataset, img['file_name']))# 通过id,得到注释的信息
annIds = coco.getAnnIds(imgIds=img['id'], catIds=cls_id, iscrowd=None)
anns = coco.loadAnns(annIds)
# coco.showAnns(anns)
objs = []
for ann in anns:
class_name = classes[ann['category_id']]
if class_name in classes_names:
if 'bbox' in ann:
bbox = ann['bbox']
xmin = int(bbox[0])
ymin = int(bbox[1])
xmax = int(bbox[2] + bbox[0])
ymax = int(bbox[3] + bbox[1])
obj = [class_name, xmin, ymin, xmax, ymax]
objs.append(obj)
return objs
for dataset in datasets_list:
# ./COCO/annotations/instances_train2014.json
annFile = '{}/annotations/instances_{}.json'.format(dataDir, dataset)
# COCO API for initializing annotated data
coco = COCO(annFile)
'''
COCO 对象创建完毕后会输出如下信息:
loading annotations into memory...
Done (t=0.81s)
creating index...
index created!
至此, json 脚本解析完毕, 并且将图片和对应的标注数据关联起来.
'''
# show all classes in coco
classes = id2name(coco)
print(classes)
# [1, 2, 3, 4, 6, 8]
classes_ids = coco.getCatIds(catNms=classes_names)
print(classes_ids)
for cls in classes_names:
# Get ID number of this class
cls_id = coco.getCatIds(catNms=[cls])
img_ids = coco.getImgIds(catIds=cls_id)
# imgIds=img_ids[0:10]
for imgId in tqdm(img_ids):
img = coco.loadImgs(imgId)[0]
filename = img['file_name']
objs = showimg(coco, dataset, img, classes, classes_ids, show=False)
save_annotations_and_imgs(coco, dataset, filename, objs)
out_img_base = 'VOCData/images'
out_xml_base = 'VOCData/Annotations'
img_base = 'VOCData/images/'
xml_base = 'VOCData/Annotations/'
if not os.path.exists(out_img_base):
os.mkdir(out_img_base)
if not os.path.exists(out_xml_base):
os.mkdir(out_xml_base)
for img in tqdm(os.listdir(img_base)):
xml = img.replace('.jpg', '.xml')
src_img = os.path.join(img_base, img)
src_xml = os.path.join(xml_base, xml)
dst_img = os.path.join(out_img_base, img)
dst_xml = os.path.join(out_xml_base, xml)
if os.path.exists(src_img) and os.path.exists(src_xml):
move(src_img, dst_img)
move(src_xml, dst_xml)
def extract_xml(infile):
with open(infile,'r') as f: #解析xml中的name标签
xml_text = f.read()
root = ET.fromstring(xml_text)
classes = []
for obj in root.iter('object'):
cls_ = obj.find('name').text
classes.append(cls_)
return classes
if __name__ == '__main__':
base = 'VOCData/Annotations/'
Xmls=[]
# Xmls = sorted([v for v in os.listdir(base) if v.endswith('.xml')])
for v in os.listdir(base):
if v.endswith('.xml'):
Xmls.append(str(v))
# iterable -- 可迭代对象。key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
print('-[INFO] total:', len(Xmls))
# print(Xmls)
labels = {'person': 0}
for xml in Xmls:
infile = os.path.join(base, xml)
# print(infile)
cls_ = extract_xml(infile)
for c in cls_:
if not c in labels:
print(infile, c)
raise
labels[c] += 1
for k, v in labels.items():
print('-[Count] {} total:{} per:{}'.format(k, v, v/len(Xmls)))
2.2按VOC格式划分数据集,train : val = 0.85 : 0.15生成标签label_list.txt
"""
按VOC格式划分数据集,train : val = 0.85 : 0.15
生成标签label_list.txt
"""
import os
import shutil
import skimage.io as io
from tqdm import tqdm
from random import shuffle
dataset = 'dataset/VOCData/'
train_txt = os.path.join(dataset, 'train_val.txt')
val_txt = os.path.join(dataset, 'val.txt')
lbl_txt = os.path.join(dataset, 'label_list.txt')
classes = [
"person"
]
with open(lbl_txt, 'w') as f:
for l in classes:
f.write(l+'\n')
xml_base = 'Annotations'
img_base = 'images'
xmls = [v for v in os.listdir(os.path.join(dataset, xml_base)) if v.endswith('.xml')]
shuffle(xmls)
split = int(0.85 * len(xmls)) #划分训练集与验证集
with open(train_txt, 'w') as f:
for x in tqdm(xmls[:split]):
m = x[:-4]+'.jpg'
xml_path = os.path.join(xml_base, x)
img_path = os.path.join(img_base, m)
f.write('{} {}\n'.format(img_path, xml_path))
with open(val_txt, 'w') as f:
for x in tqdm(xmls[split:]):
m = x[:-4]+'.jpg'
xml_path = os.path.join(xml_base, x)
img_path = os.path.join(img_base, m)
f.write('{} {}\n'.format(img_path, xml_path))
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml&q