e智团队实验室项目-数据集的整理和命名和格式转换
赵雅玲 *, 张钊* ,赵尉*
(淮北师范大学计算机科学与技术学院,淮北师范大学经济与管理学院,安徽 淮北)
*These authors contributed to the work equllly and should be regarded as co-first authors.
🌞欢迎来到深度学习的世界
🌈博客主页:卿云阁💌欢迎关注🎉点赞👍收藏⭐️留言📝
🌟本文由卿云阁原创!
🌠本阶段属于练气阶段,希望各位仙友顺利完成突破
📆首发时间:🌹2022年11月10日🌹
✉️希望可以和大家一起完成进阶之路!
🙏作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!
目录
🍈 数据集的划分
对机器学习和深度学习而言,都需要进行训练集和测试集的划分,在运行一些目标检测算法的时候,经常需要手写代码进行划分,这里为大家整理好了一份代码。
# 将图片和标注数据按比例切分为 训练集和测试集 import shutil import random import os # 原始路径 image_original_path = 'D:\sraffic_news\images/' label_original_path = 'D:\sraffic_news\labels/' # 训练集路径 train_image_path = 'D:\sraffic_news\ train\images/' train_label_path = 'D:\sraffic_news\ train\labels/' # 验证集路径 val_image_path = 'D:\sraffic_news\ val\images/' val_label_path = 'D:\sraffic_news\ val\labels/' # 测试集路径 test_image_path = 'D:\sraffic_news\ test\images/' test_label_path = 'D:\sraffic_news\ test\labels/' # 数据集划分比例,训练集75%,验证集15%,测试集15% train_percent = 0.8 val_percent = 0.1 test_percent = 0.1 # 检查文件夹是否存在 def mkdir(): if not os.path.exists(train_image_path): os.makedirs(train_image_path) if not os.path.exists(train_label_path): os.makedirs(train_label_path) if not os.path.exists(val_image_path): os.makedirs(val_image_path) if not os.path.exists(val_label_path): os.makedirs(val_label_path) if not os.path.exists(test_image_path): os.makedirs(test_image_path) if not os.path.exists(test_label_path): os.makedirs(test_label_path) def main(): mkdir() total_txt = os.listdir(label_original_path) num_txt = len(total_txt) list_all_txt = range(num_txt) # 范围 range(0, num) num_train = int(num_txt * train_percent) num_val = int(num_txt * val_percent) num_test = num_txt - num_train - num_val train = random.sample(list_all_txt, num_train) # train从list_all_txt取出num_train个元素 # 所以list_all_txt列表只剩下了这些元素:val_test val_test = [i for i in list_all_txt if not i in train] # 再从val_test取出num_val个元素,val_test剩下的元素就是test val = random.sample(val_test, num_val) # 检查两个列表元素是否有重合的元素 # set_c = set(val_test) & set(val) # list_c = list(set_c) # print(list_c) # print(len(list_c)) print("训练集数目:{}, 验证集数目:{},测试集数目:{}".format(len(train), len(val), len(val_test) - len(val))) for i in list_all_txt: name = total_txt[i][:-4] srcImage = image_original_path + name + '.jpg' srcLabel = label_original_path + name + '.txt' if i in train: dst_train_Image = train_image_path + name + '.jpg' dst_train_Label = train_label_path + name + '.txt' shutil.copyfile(srcImage, dst_train_Image) shutil.copyfile(srcLabel, dst_train_Label) elif i in val: dst_val_Image = val_image_path + name + '.jpg' dst_val_Label = val_label_path + name + '.txt' shutil.copyfile(srcImage, dst_val_Image) shutil.copyfile(srcLabel, dst_val_Label) else: dst_test_Image = test_image_path + name + '.jpg' dst_test_Label = test_label_path + name + '.txt' shutil.copyfile(srcImage, dst_test_Image) shutil.copyfile(srcLabel, dst_test_Label) if __name__ == '__main__': main()
🍉命名
首先,大家第一时间想到的肯定是在文件夹中Ctrl+A全选,接着,右键选择重命名,或者是下载一个图片处理工具,但是前者却会出现下图的问题,命名后会出现烦人的“()”,不符合要求;而后者,先不说下载耽误时间,如果对于处理大量图片命名的工程是极其慢的(本人曾尝试过),因为当你下载好软件后,你要将所有图片一一上传至该软件,之后再一张一张的命名和保存(该过程是无法操作的,只能苦苦等待),整个过程下来已经超过了截止时间了。接下来我来介绍一种可以超快速给大量图片批量名的方法,请小伙伴们认真学习。
操作步骤:
打开文件夹,点击右上角箭头,接着Ctrl+A全选图片,
点击左上角的“复制路径”(就是复制了所有图片的地址),打开Excel表格,将其粘贴到表格中;
之后手动提取图片的后缀名称“绿灯(1).jpg”到第二列,然后按下Ctrl+E批量提取;
然后再第三列输入你想要替换的图片名;
接下来将代码(="ren """&B2&""" "&C2)输入到第四列后,按回车,双击右下角填充代码,如下图,代码中的B2、C2分别是被替换名和替换名,可以根据需要随意调整,其中“ren”是rename的简写,
该代码的公式为:ren+空格+旧图片名+空格+新文件名;
然后复制所有的代码,在图片文件夹中新建一个txt文档,把代码粘贴进去,保存文本文档;
将编码改为ANSl,再将文件名后缀改为“.BAT”,然后保存后,运行生成的.BAT文件,然后图片的批量修改就完成了!
🍻格式的转换
对于目标检测算法,一共有两种形式的标签。一种是txt格式,一种是xml格式。
txt与xml格式的转换
from xml.dom.minidom import Document import os import cv2 # def makexml(txtPath, xmlPath, picPath): # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径 def makexml(picPath, txtPath, xmlPath): # txt所在文件夹路径,xml文件保存路径,图片所在文件夹路径 """此函数用于将yolo格式txt标注文件转换为voc格式xml标注文件 在自己的标注图片文件夹下建三个子文件夹,分别命名为picture、txt、xml """ dic = {'0': "green", # 创建字典用来对类型进行转换 '1': "red", # 此处的字典要与自己的classes.txt文件中的类对应,且顺序要一致 } files = os.listdir(txtPath) for i, name in enumerate(files): xmlBuilder = Document() annotation = xmlBuilder.createElement("annotation") # 创建annotation标签 xmlBuilder.appendChild(annotation) txtFile = open(txtPath + name) txtList = txtFile.readlines() img = cv2.imread(picPath + name[0:-4] + ".jpg") Pheight, Pwidth, Pdepth = img.shape folder = xmlBuilder.createElement("folder") # folder标签 foldercontent = xmlBuilder.createTextNode("driving_annotation_dataset") folder.appendChild(foldercontent) annotation.appendChild(folder) # folder标签结束 filename = xmlBuilder.createElement("filename") # filename标签 filenamecontent = xmlBuilder.createTextNode(name[0:-4] + ".jpg") filename.appendChild(filenamecontent) annotation.appendChild(filename) # filename标签结束 size = xmlBuilder.createElement("size") # size标签 width = xmlBuilder.createElement("width") # size子标签width widthcontent = xmlBuilder.createTextNode(str(Pwidth)) width.appendChild(widthcontent) size.appendChild(width) # size子标签width结束 height = xmlBuilder.createElement("height") # size子标签height heightcontent = xmlBuilder.createTextNode(str(Pheight)) height.appendChild(heightcontent) size.appendChild(height) # size子标签height结束 depth = xmlBuilder.createElement("depth") # size子标签depth depthcontent = xmlBuilder.createTextNode(str(Pdepth)) depth.appendChild(depthcontent) size.appendChild(depth) # size子标签depth结束 annotation.appendChild(size) # size标签结束 for j in txtList: oneline = j.strip().split(" ") object = xmlBuilder.createElement("object") # object 标签 picname = xmlBuilder.createElement("name") # name标签 namecontent = xmlBuilder.createTextNode(dic[oneline[0]]) picname.appendChild(namecontent) object.appendChild(picname) # name标签结束 pose = xmlBuilder.createElement("pose") # pose标签 posecontent = xmlBuilder.createTextNode("Unspecified") pose.appendChild(posecontent) object.appendChild(pose) # pose标签结束 truncated = xmlBuilder.createElement("truncated") # truncated标签 truncatedContent = xmlBuilder.createTextNode("0") truncated.appendChild(truncatedContent) object.appendChild(truncated) # truncated标签结束 difficult = xmlBuilder.createElement("difficult") # difficult标签 difficultcontent = xmlBuilder.createTextNode("0") difficult.appendChild(difficultcontent) object.appendChild(difficult) # difficult标签结束 bndbox = xmlBuilder.createElement("bndbox") # bndbox标签 xmin = xmlBuilder.createElement("xmin") # xmin标签 mathData = int(((float(oneline[1])) * Pwidth + 1) - (float(oneline[3])) * 0.5 * Pwidth) xminContent = xmlBuilder.createTextNode(str(mathData)) xmin.appendChild(xminContent) bndbox.appendChild(xmin) # xmin标签结束 ymin = xmlBuilder.createElement("ymin") # ymin标签 mathData = int(((float(oneline[2])) * Pheight + 1) - (float(oneline[4])) * 0.5 * Pheight) yminContent = xmlBuilder.createTextNode(str(mathData)) ymin.appendChild(yminContent) bndbox.appendChild(ymin) # ymin标签结束 xmax = xmlBuilder.createElement("xmax") # xmax标签 mathData = int(((float(oneline[1])) * Pwidth + 1) + (float(oneline[3])) * 0.5 * Pwidth) xmaxContent = xmlBuilder.createTextNode(str(mathData)) xmax.appendChild(xmaxContent) bndbox.appendChild(xmax) # xmax标签结束 ymax = xmlBuilder.createElement("ymax") # ymax标签 mathData = int(((float(oneline[2])) * Pheight + 1) + (float(oneline[4])) * 0.5 * Pheight) ymaxContent = xmlBuilder.createTextNode(str(mathData)) ymax.appendChild(ymaxContent) bndbox.appendChild(ymax) # ymax标签结束 object.appendChild(bndbox) # bndbox标签结束 annotation.appendChild(object) # object标签结束 f = open(xmlPath + name[0:-4] + ".xml", 'w') xmlBuilder.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='utf-8') f.close() if __name__ == "__main__": picPath = "D:\VOCdevkit/VOC2007/JPEGImages/" # 图片所在文件夹路径,后面的/一定要带上 txtPath = "D:\VOCdevkit/VOC2007/YOLO/" # txt所在文件夹路径,后面的/一定要带上 xmlPath = "D:\VOCdevkit/VOC2007/Annotations/" # xml文件保存路径,后面的/一定要带上 makexml(picPath, txtPath, xmlPath)
xml与txt格式的转换
import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join import glob classes = ["green", "red"] def convert(size, box): dw = 1.0 / size[0] dh = 1.0 / size[1] x = (box[0] + box[1]) / 2.0 y = (box[2] + box[3]) / 2.0 w = box[1] - box[0] h = box[3] - box[2] x = x * dw w = w * dw y = y * dh h = h * dh return (x, y, w, h) def convert_annotation(image_name): in_file = open('./datasets/Annotations/outputs/' + image_name[:-3] + 'xml') # xml文件路径 out_file = open('./datasets/ImageSets/' + image_name[:-3] + 'txt', 'w') # 转换后的txt文件存放路径 f = open('./datasets/Annotations/outputs/' + image_name[:-3] + 'xml') xml_text = f.read() root = ET.fromstring(xml_text) f.close() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) for obj in root.iter('object'): cls = obj.find('name').text if cls not in classes: print(cls) continue cls_id = classes.index(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)) bb = convert((w, h), b) out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') wd = getcwd() if __name__ == '__main__': for image_path in glob.glob("./datasets/images/*.jpg"): # 每一张图片都对应一个xml文件这里写xml对应的图片的路径 image_name = image_path.split('\\')[-1] convert_annotation(image_name)
Institutional Review Board Statement: Not applicable.
Informed Consent Statement: Not applicable.
Data Availability Statement: Not applicable.
Author Contributions:All authors participated in the assisting performance study and approved the paper.
Conflicts of Interest: The authors declare no conflict of interes