【深度学习】【Python】【Widerface数据集】 转VOC格式,VOC 转YOLOv5格式,YOLOv5训练WiderFace数据集,检查yolo labels对不对
文章目录
- Widerface数据集转VOC格式
- VOC 转YOLO格式
- 数据集的imageslisttxt
- YOLOv5训练
- 检查yolo labels对不对
- 并行训练
Widerface数据集转VOC格式
标注是:
下面程序folderFile 字典定义了数据集存储的位置信息,VOCrootpath 给出了VOC存储地址。
# coding:utf-8
import os.path
from xml.dom.minidom import Document
import cv2
import numpy as npdef writexml(filename, saveimg, bboxes, xmlpath):doc = Document()annotation = doc.createElement('annotation')doc.appendChild(annotation)folder = doc.createElement('folder')folder_name = doc.createTextNode('widerface')folder.appendChild(folder_name)annotation.appendChild(folder)filenamenode = doc.createElement('filename')filename_name = doc.createTextNode(filename)filenamenode.appendChild(filename_name)annotation.appendChild(filenamenode)source = doc.createElement('source')annotation.appendChild(source)database = doc.createElement('database')database.appendChild(doc.createTextNode('wider face Database'))source.appendChild(database)annotation_s = doc.createElement('annotation')annotation_s.appendChild(doc.createTextNode('PASCAL VOC2007'))source.appendChild(annotation_s)image = doc.createElement('image')image.appendChild(doc.createTextNode('flickr'))source.appendChild(image)flickrid = doc.createElement('flickrid')flickrid.appendChild(doc.createTextNode('-1'))source.appendChild(flickrid)owner = doc.createElement('owner')annotation.appendChild(owner)flickrid_o = doc.createElement('flickrid')flickrid_o.appendChild(doc.createTextNode('muke'))owner.appendChild(flickrid_o)name_o = doc.createElement('name')name_o.appendChild(doc.createTextNode('muke'))owner.appendChild(name_o)size = doc.createElement('size')annotation.appendChild(size)width = doc.createElement('width')width.appendChild(doc.createTextNode(str(saveimg.shape[1])))height = doc.createElement('height')height.appendChild(doc.createTextNode(str(saveimg.shape[0])))depth = doc.createElement('depth')depth.appendChild(doc.createTextNode(str(saveimg.shape[2])))size.appendChild(width)size.appendChild(height)size.appendChild(depth)segmented = doc.createElement('segmented')segmented.appendChild(doc.createTextNode('0'))annotation.appendChild(segmented)for i in range(len(bboxes)):bbox = bboxes[i]objects = doc.createElement('object')annotation.appendChild(objects)object_name = doc.createElement('name')object_name.appendChild(doc.createTextNode('face'))objects.appendChild(object_name)pose = doc.createElement('pose')pose.appendChild(doc.createTextNode('Unspecified'))objects.appendChild(pose)truncated = doc.createElement('truncated')truncated.appendChild(doc.createTextNode('0'))objects.appendChild(truncated)difficult = doc.createElement('difficult')difficult.appendChild(doc.createTextNode('0'))objects.appendChild(difficult)bndbox = doc.createElement('bndbox')objects.appendChild(bndbox)xmin = doc.createElement('xmin')xmin.appendChild(doc.createTextNode(str(bbox[0])))bndbox.appendChild(xmin)ymin = doc.createElement('ymin')ymin.appendChild(doc.createTextNode(str(bbox[1])))bndbox.appendChild(ymin)xmax = doc.createElement('xmax')xmax.appendChild(doc.createTextNode(str(bbox[0] + bbox[2])))bndbox.appendChild(xmax)ymax = doc.createElement('ymax')ymax.appendChild(doc.createTextNode(str(bbox[1] + bbox[3])))bndbox.appendChild(ymax)f = open(xmlpath, "w")f.write(doc.toprettyxml(indent=''))f.close()if __name__ == '__main__':# 给出下面五个路径folderFile = {"traintxt": r"E:\WIIDERFACE\wider_face_split\wider_face_split\wider_face_train_bbx_gt.txt","trainimagepath": r"E:\WIIDERFACE\WIDER_train\WIDER_train\images","valtxt": r"E:\WIIDERFACE\wider_face_split\wider_face_split\wider_face_val_bbx_gt.txt","valimagepath": r"E:\WIIDERFACE\WIDER_val\WIDER_val\images","texttxt": r"E:\WIIDERFACE\wider_face_split\wider_face_split\wider_face_test_filelist.txt","textimagepath": r"E:\WIIDERFACE\WIDER_test\WIDER_test\images", }# 给出VOC数据存储地址VOCrootpath = r"E:\WIIDERFACE\WIDER_VOC"needPath = [os.path.join(VOCrootpath, "train", "Annotations"),os.path.join(VOCrootpath, "train", "JPEGImages"),os.path.join(VOCrootpath, "val", "Annotations"),os.path.join(VOCrootpath, "val", "JPEGImages"),os.path.join(VOCrootpath, "test", "JPEGImages"), ]for ph in needPath:if not os.path.exists(ph):os.makedirs(ph)for gtfile, gtimages, imgsavepath, vocxmlsavepath in [(folderFile["traintxt"], folderFile["trainimagepath"], needPath[1], needPath[0]),(folderFile["valtxt"], folderFile["valimagepath"], needPath[3], needPath[2])]:with open(gtfile, "r", encoding="utf-8") as f:while True:gt_con = f.readline().strip()if gt_con is None or gt_con == "":breakim_path = os.path.join(gtimages, gt_con)im_data = cv2.imdecode(np.fromfile(im_path, dtype=np.uint8), 1) # img是矩阵if im_data is None:continuenumbox = int(f.readline())bboxes = []if numbox == 0: # numbox 为0 的情况处理f.readline()else:for i in range(numbox):line = f.readline()infos = line.split(" ") # 用空格分割bbox = (int(infos[0]), int(infos[1]), int(infos[2]), int(infos[3]))bboxes.append(bbox) # 将一张图片的所有人脸数据加入bboxesfilename = gt_con.replace("/", "_").replace("-", "_")[:-4] # 将存储位置作为图片名称,斜杠转为下划线cv2.imencode('.jpg', im_data)[1].tofile(os.path.join(imgsavepath, filename + ".jpg"))xmlpath = os.path.join(vocxmlsavepath, filename + ".xml")writexml(filename, im_data, bboxes, xmlpath)gtfile = folderFile["texttxt"]gtimages = folderFile["textimagepath"]imgsavepath = needPath[4]with open(gtfile, "r", encoding="utf-8") as f:while True:gt_con = f.readline().strip()if gt_con is None or gt_con == "":breakim_path = os.path.join(gtimages, gt_con)im_data = cv2.imdecode(np.fromfile(im_path, dtype=np.uint8), 1) # img是矩阵if im_data is None:continuefilename = gt_con.replace("/", "_").replace("-", "_")[:-4] # 将存储位置作为图片名称,斜杠转为下划线cv2.imencode('.jpg', im_data)[1].tofile(os.path.join(imgsavepath, filename + ".jpg"))
VOC 转YOLO格式
YOLO格式:
下面的代码会在各自的Annotations同级目录创建出labels文件夹,然后将Annotations内的xml标注转换成yolov5的标注文件:
# coding:utf-8
import os
import os.path
import xml.etree.ElementTree as ETdef convert_annotation(xmldir: str, txtdir: str, image_id: str, classes: dict):in_file = open(os.path.join(xmldir, '%s.xml' % (image_id)), 'r', encoding='UTF-8')out_file = open(os.path.join(txtdir, '%s.txt' % (image_id)), 'w')tree = ET.parse(in_file)root = tree.getroot()size = root.find('size')size_width = int(size.find('width').text)size_height = int(size.find('height').text)for obj in root.iter('object'):difficult = obj.find('difficult').textcls = obj.find('name').textif cls not in classes or int(difficult) == 1:continuecls_id = classes[cls]xmlbox = obj.find('bndbox')b = [float(xmlbox.find('xmin').text),float(xmlbox.find('xmax').text),float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text)]if size_width == 0 or size_height == 0 or b[0] == b[1] or b[2] == b[3]:print("不合理的图不再给labels ", image_id)# if os.path.exists(xmldir + '%s.xml' % (image_id)):# os.remove(xmldir + '%s.xml' % (image_id))out_file.close()os.remove(os.path.join(txtdir, '%s.txt' % (image_id)))return 1# 标注越界修正if b[0] < 0:b[0] = 0if b[1] > size_width:b[1] = size_widthif b[2] < 0:b[2] = 0if b[3] > size_height:b[3] = size_heighttxt_data = [round(((b[0] + b[1]) / 2.0 - 1) / size_width, 6),round(((b[2] + b[3]) / 2.0 - 1) / size_height, 6),round((b[1] - b[0]) / size_width, 6),round((b[3] - b[2]) / size_height, 6)]if txt_data[0] < 0 or txt_data[1] < 0 or txt_data[2] < 0 or txt_data[3] < 0:print("不合理的图不再给labels ", image_id)out_file.close()os.remove(os.path.join(txtdir, '%s.txt' % (image_id)))return 1out_file.write(str(cls_id) + " " + " ".join([str(a) for a in txt_data]) + '\n')in_file.close()out_file.close()return 0def listPathAllfiles(dirname):result = []for maindir, subdir, file_name_list in os.walk(dirname):for filename in file_name_list:apath = os.path.join(maindir, filename)result.append(apath)return resultif __name__ == '__main__':classes = {'face': 0} # 标签名:标签id# 给出VOC数据存储地址VOCrootpath = r"E:\WIIDERFACE\WIDER_VOC"needPath = [os.path.join(VOCrootpath, "train", "Annotations"),os.path.join(VOCrootpath, "train", "JPEGImages"),os.path.join(VOCrootpath, "val", "Annotations"),os.path.join(VOCrootpath, "val", "JPEGImages"),os.path.join(VOCrootpath, "test", "JPEGImages"),os.path.join(VOCrootpath, "train", "labels"),os.path.join(VOCrootpath, "val", "labels"), ]for ph in needPath:if not os.path.exists(ph):os.makedirs(ph)for xmlpath, txtpath in [[needPath[0], needPath[5]],[needPath[2], needPath[6]]]:allfiles = listPathAllfiles(xmlpath)print("一共有文件个数:", len(allfiles))failNum = 0for xmlName in allfiles:# xml存储路径,yololabels存储路径,xml文件名称不带.xml后缀,需要的类及其类id的字典if convert_annotation(xmlpath, txtpath, os.path.basename(xmlName)[:-4], classes) == 1:failNum += 1print("失败了多少个文件的labels:", failNum)
会遇到一些xml里面标注不合规,但是没多少,无关紧要了。但得注意,标签不行就不要给txt文件,里面没内容的txt文件yolo会认为是对应图里没目标。
C:\Users\dong.xie\.conda\envs\py38\python.exe C:/Users/dong.xie/Desktop/workcode/kevintest/dataset_cleaner/005VOC转yolo.py
一共有文件个数: 12880
不合理的图不再给labels 0__Parade_0_Parade_Parade_0_452
不合理的图不再给labels 12__Group_12_Group_Large_Group_12_Group_Large_Group_12_31
不合理的图不再给labels 29__Students_Schoolkids_29_Students_Schoolkids_Students_Schoolkids_29_230
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstration_Or_Protest_2_202
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstration_Or_Protest_2_520
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstration_Or_Protest_2_543
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstration_Or_Protest_2_546
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstration_Or_Protest_2_666
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstrators_2_206
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstrators_2_373
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstrators_2_559
不合理的图不再给labels 2__Demonstration_2_Demonstration_Political_Rally_2_444
不合理的图不再给labels 2__Demonstration_2_Demonstration_Political_Rally_2_71
不合理的图不再给labels 2__Demonstration_2_Demonstration_Protesters_2_346
不合理的图不再给labels 33__Running_33_Running_Running_33_660
不合理的图不再给labels 35__Basketball_35_Basketball_basketballgame_ball_35_805
不合理的图不再给labels 35__Basketball_35_Basketball_Basketball_35_102
不合理的图不再给labels 35__Basketball_35_Basketball_Basketball_35_220
不合理的图不再给labels 36__Football_36_Football_americanfootball_ball_36_184
不合理的图不再给labels 36__Football_36_Football_Football_36_63
不合理的图不再给labels 39__Ice_Skating_39_Ice_Skating_iceskiing_39_380
不合理的图不再给labels 46__Jockey_46_Jockey_Jockey_46_576
不合理的图不再给labels 46__Jockey_46_Jockey_Jockey_46_717
不合理的图不再给labels 48__Parachutist_Paratrooper_48_Parachutist_Paratrooper_Parachutist_Paratrooper_48_258
不合理的图不再给labels 48__Parachutist_Paratrooper_48_Parachutist_Paratrooper_Parachutist_Paratrooper_48_283
不合理的图不再给labels 54__Rescue_54_Rescue_rescuepeople_54_29
不合理的图不再给labels 58__Hockey_58_Hockey_icehockey_puck_58_947
不合理的图不再给labels 7__Cheering_7_Cheering_Cheering_7_17
失败了多少个文件的labels: 28
一共有文件个数: 3226
不合理的图不再给labels 0__Parade_0_Parade_Parade_0_275
不合理的图不再给labels 0__Parade_0_Parade_Parade_0_317
不合理的图不再给labels 2__Demonstration_2_Demonstration_Demonstration_Or_Protest_2_476
不合理的图不再给labels 2__Demonstration_2_Demonstration_Political_Rally_2_335
不合理的图不再给labels 37__Soccer_37_Soccer_soccer_ball_37_281
不合理的图不再给labels 39__Ice_Skating_39_Ice_Skating_iceskiing_39_583
不合理的图不再给labels 50__Celebration_Or_Party_50_Celebration_Or_Party_houseparty_50_715
不合理的图不再给labels 7__Cheering_7_Cheering_Cheering_7_171
不合理的图不再给labels 7__Cheering_7_Cheering_Cheering_7_426
失败了多少个文件的labels: 9Process finished with exit code 0
数据集的imageslisttxt
此时获得了这样的文件层级结构:
E:\WIIDERFACE\WIDER_VOC
├─test
│ └─JPEGImages
├─train
│ ├─Annotations
│ ├─JPEGImages
│ └─labels
└─val
├─Annotations
├─JPEGImages
└─labels
为了便于yolov5识别,将三个JPEGImages名称改写为images。
同时,生成三个images的txtlist便于yolov5识别,下面程序即会在E:\WIIDERFACE\WIDER_VOC目录生成对应imageslisttxt:
import osdef listPathAllfiles(dirname):result = []for maindir, subdir, file_name_list in os.walk(dirname):for filename in file_name_list:apath = os.path.join(maindir, filename)result.append(apath)return resultif __name__ == '__main__':classes = {'face': 0} # 标签名:标签id# 给出VOC数据存储地址VOCrootpath = r"E:\WIIDERFACE\WIDER_VOC"needPath = [os.path.join(VOCrootpath, "train", "Annotations"),os.path.join(VOCrootpath, "train", "images"),os.path.join(VOCrootpath, "val", "Annotations"),os.path.join(VOCrootpath, "val", "images"),os.path.join(VOCrootpath, "test", "images"),os.path.join(VOCrootpath, "train", "labels"),os.path.join(VOCrootpath, "val", "labels"), ]for imagespath in [needPath[1], needPath[3], needPath[4]]:allfiles = listPathAllfiles(imagespath)fatherpath = os.path.dirname(imagespath)txtname = os.path.basename(fatherpath)f = open(os.path.join(VOCrootpath, txtname + ".txt"), "w", encoding="utf-8")allfiles = list(map(lambda x: x.replace("\\", "/"), allfiles))f.write("\n".join(allfiles))f.close()print(imagespath, "图片数量", len(allfiles))
E:\WIIDERFACE\WIDER_VOC\train\images 图片数量 12880
E:\WIIDERFACE\WIDER_VOC\val\images 图片数量 3226
E:\WIIDERFACE\WIDER_VOC\test\images 图片数量 16097
YOLOv5训练
写数据yaml文件,下载权重文件:
path: E:\WIIDERFACE\WIDER_VOC # dataset root dir
train: train.txt # train images (relative to 'path') 118287 images
val: val.txt # val images (relative to 'path') 5000 images
test: test.txt # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794# Classes
nc: 1 # number of classes
names: ['face'] # class names
训练:
python train.py --batch-size 4 --data widerFace.yaml --img 640 --epochs 10 --weight weights/yolov5m.pt
看到这个样子就行:
检查yolo labels对不对
import osimport cv2
import matplotlib.pyplot as plt
import numpy as npASSETS_DIRECTORY = "assets"
plt.rcParams["savefig.bbox"] = "tight"def listPathAllfiles(dirname):result = []for maindir, subdir, file_name_list in os.walk(dirname):for filename in file_name_list:apath = os.path.join(maindir, filename)result.append(apath)return resultif __name__ == '__main__':labelspath = r'E:\WIIDERFACE\WIDER_VOC\train\labels'imagespath = r'E:\WIIDERFACE\WIDER_VOC\train\images'labelsFiles = listPathAllfiles(labelspath)for lbf in labelsFiles:labels = open(lbf, "r").readlines()labels = list(map(lambda x: x.strip().split(" "), labels))imgfileName = os.path.join(imagespath, os.path.basename(lbf)[:-4] + ".jpg")img = cv2.imdecode(np.fromfile(imgfileName, dtype=np.uint8), 1) # img是矩阵for lbs in labels:lb = list(map(float, lbs))[1:]x1 = int((lb[0] - lb[2] / 2) * img.shape[1])y1 = int((lb[1] - lb[3] / 2) * img.shape[0])x2 = int((lb[0] + lb[2] / 2) * img.shape[1])y2 = int((lb[1] + lb[3] / 2) * img.shape[0])cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 5)cv2.imshow("1", img)cv2.waitKey()cv2.destroyAllWindows()
并行训练
python -m torch.distributed.launch --nproc_per_node 4 train.py --batch-size 128 --data widerFace.yaml --img 640 --epochs 400 --weight weights/yolov5m.pt --device 0,1,2,3
【深度学习】【Python】【Widerface数据集】 转VOC格式,VOC 转YOLOv5格式,YOLOv5训练WiderFace数据集,检查yolo labels对不对相关推荐
- python 动物分类_《python深度学习》笔记---5.3-1、猫狗分类(使用预训练网络)
<python深度学习>笔记---5.3-1.猫狗分类(使用预训练网络) 一.总结 一句话总结: [小型图像数据集]:想要将深度学习应用于小型图像数据集,一种常用且非常高效的方法是使用预训 ...
- 深度学习小技巧(二):如何保存和恢复scikit-learn训练的模型
深度学习小技巧(一):如何保存和恢复TensorFlow训练的模型 在许多情况下,在使用scikit学习库的同时,你需要将预测模型保存到文件中,然后在使用它们的时候还原它们,以便重复使用以前的工作.比 ...
- 深度学习之数据处理——如何将图片和标签打乱并划分为训练集和测试集
深度学习之数据处理--如何将图片和标签打乱并划分为训练集和测试集 记录我的第一篇CSDN博客 最近我在网上找到Office31数据集,这个数据集中包含了三个子数据集,分别为:Amazon.dslr.w ...
- 阿里云深度学习实验室(DL-Lab) -- 基于Docker和EGS一键创建高性能Tensorflow分布式训练
原文链接:点击打开链接 摘要: ## 一. 概述 Tensorflow是目前使用最为广泛的深度学习框架之一,但是目前搭建分布式多机多卡训练比较困难,而且Tensorflow原生的分布式的性能很差. 为 ...
- 4.keras实现--生成式深度学习之用变分自编码器VAE生成图像(mnist数据集和名人头像数据集)...
1.VAE和GAN 变分自编码器(VAE,variatinal autoencoder) VS 生成式对抗网络(GAN,generative adversarial network) 两者不 ...
- 深度学习和目标检测系列教程 17-300: 3 个类别面罩检测类别数据集训练yolov5s模型
@Author:Runsen YOLO 是目前最火爆的的计算机视觉算法之一,今天使用的数据集来源:https://www.kaggle.com/andrewmvd/face-mask-detectio ...
- 最简单深度学习Python实现(二分类问题)
二分类问题指的是所有数据的标签就只有两种,正面或者负面. 一,准备数据 我们使用的数据是内置于Keras的IMDB数据集.它包含50000条两极分化的电影评论,正面评论和负面评论各占一半.其中2500 ...
- 百度飞桨深度学习Python小白逆袭大神7日结营心得
很有幸参加了百度飞桨的Python小白逆袭大神7天打卡营.七天的学习已经接近了尾声.现在回顾一下这次的课程,收获颇丰.相信很多参加的学员都感受颇丰,从小白入门到自主大作业完成,我们不仅了解了深度学习的 ...
- 建议收藏!耗时3个月收集的机器学习+深度学习+Python资料教程~免费分享了
2019年,IT寒冬来势汹汹,许多IT从业者遭遇降薪.裁员.找工作难等问题,在即将到来的2020年形势依然不容乐观. 程序员作为曾经备受羡慕的高薪群体,如今也面临着"保饭碗"的巨大 ...
最新文章
- spring根据名称获取bean_带你从零开始手写 spring ioc 框架,深入学习 spring 源码
- 【126】TensorFlow 使用皮尔逊相关系数找出和标签相关性最大的特征值
- java 导出pdf_一次java导出pdf的经历
- windows设置自动清理log
- LeetCode 1909. 删除一个元素使数组严格递增
- Expression Blend 2 September Preview is now available!(中文版)
- 【Todo】【读书笔记】Linux高性能服务器编程
- Linux企业级项目实践之网络爬虫(29)——遵守robots.txt
- java字符串不足后面补0,JAVA字符串格式化长度不足补0
- matlab中garchred是什么意思,garch模型matlab
- Supervisor进程管理详解
- 2022-2027年中国海参行业市场深度分析及投资战略规划报告
- 安全、智慧是 Oppo 快充技术最新的发展方向
- php当月1号怎么获取,php获取下月1号和月底最后一天的时间
- 手机连接投影机的步骤_手机怎么连接投影仪?这几招实用
- 浅谈策略交易、系统交易和程式交易
- 老男孩python2020年31期学习记录贴
- 英国情报机构授权开设“网络间谍”硕士专业!
- 企业wifi管家带来无限商机,你看到了吗?
- Kettle使用笔记
热门文章
- if or函数套用_Excel将IF函数和OR函数结合使用进行多条件的选择性判断
- 刷屏的Google Pay:羊毛是你的,你是我的
- Typescript 史上最强学习入门文章 ( 2w 字)
- Cmake 命令语句(一)
- php购物车订单业务逻辑,购物车业务逻辑
- 【通俗向】假设检验(三):卡方检验和t检验
- Revit二次开发 外部命令和外部应用
- 捕获SQLIntegrityConstraintViolationException
- 模块“DAO350.DLL”可能与你正在运行的windows版本不兼容
- 抖音html数字9,抖音687是什么意思