任务一
1.进入yolo的文件夹下,终端运行 pip install -r requirements.txt
2.数据标注:将官方提供的未打标图片.jpg,用labelImg进行标注,保存为.xml格式。(记得保存在指定的文件夹,最后提交官方)
3.将.xml数据上传云端,与云端数据合并(如果觉得自己打标的质量一般,可以跳过这一步)
4.将官方提供的.xml转换为yolo格式.txt(用下面这个脚本)
In [ ]:
#xml2yolo 将xml格式转换为yolo可用的txt #!/usr/bin/env python # -*- coding: utf8 -*- import os import sys from xml.etree import ElementTree from xml.etree.ElementTree import Element, SubElement from lxml import etree import codecs import cv2 from glob import glob XML_EXT = '.xml' ENCODE_METHOD = 'utf-8' class PascalVocReader: def __init__(self, filepath): # shapes type: # [labbel, [(x1,y1), (x2,y2), (x3,y3), (x4,y4)], color, color, difficult] self.shapes = [] self.filepath = filepath self.verified = False try: self.parseXML() except: pass def getShapes(self): return self.shapes def addShape(self, label, bndbox, filename, difficult): xmin = int(bndbox.find('xmin').text) ymin = int(bndbox.find('ymin').text) xmax = int(bndbox.find('xmax').text) ymax = int(bndbox.find('ymax').text) points = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)] self.shapes.append((label, points, filename, difficult)) def parseXML(self): assert self.filepath.endswith(XML_EXT), "Unsupport file format" parser = etree.XMLParser(encoding=ENCODE_METHOD) xmltree = ElementTree.parse(self.filepath, parser=parser).getroot() filename = xmltree.find('filename').text path = xmltree.find('path').text try: verified = xmltree.attrib['verified'] if verified == 'yes': self.verified = True except KeyError: self.verified = False for object_iter in xmltree.findall('object'): bndbox = object_iter.find("bndbox") label = object_iter.find('name').text # Add chris difficult = False if object_iter.find('difficult') is not None: difficult = bool(int(object_iter.find('difficult').text)) self.addShape(label, bndbox, path, difficult) return True classes = dict() num_classes = 0 try: input = raw_input except NameError: pass dirpath = "../datasets/coco128/images/image_new/train_0_10_xml/" #xml路径 classes_txt = '../datasets/coco128/images/image_new/classes_txt/' #classes.txt路径 ext = '.jpg' #input("Image file extension: ") '.jpg' #不用改 dirpath_img = '../datasets/coco128/images/image_new/all_img/' #xml对应的图像路径 dirpat_txt = '../datasets/labels/train/' #txt存放路径 if os.path.isfile(classes_txt): with open(classes_txt, "r") as f: class_list = f.read().strip().split() classes = {k : v for (v, k) in enumerate(class_list)} filePaths = glob(dirpath_img + "/*" + ext) #图像路径+文件 xmlNames = os.listdir(dirpath) # filePaths = glob(dirpath_img + "/*.xml") #xmlName = xmlNames[0] for xmlName in xmlNames: # filePath = os.path.splitext(filePath)[0] # fileName = os.path.splitext(filePath)[-2] imgFile = dirpath_img + '/' + xmlName.split(".")[0] + ".jpg" txtFile = dirpat_txt + '/' + xmlName.split(".")[0] + ".txt" xmlFile = dirpath + '/' + xmlName.split(".")[0] + ".xml" with open(txtFile, "w") as f: if not os.path.isfile(xmlFile): continue tVocParseReader = PascalVocReader(xmlFile) shapes = tVocParseReader.getShapes() for shape in shapes: class_name = shape[0] box = shape[1] filename = imgFile #dirpath_img + ext #filePath + ext if class_name not in classes.keys(): classes[class_name] = num_classes num_classes += 1 class_idx = classes[class_name] print(filename) (height, width, _) = cv2.imread(filename).shape cv2.imread(filename) coord_min = box[0] coord_max = box[2] xcen = float((coord_min[0] + coord_max[0])) / 2 / width ycen = float((coord_min[1] + coord_max[1])) / 2 / height w = float((coord_max[0] - coord_min[0])) / width h = float((coord_max[1] - coord_min[1])) / height f.write("%d %.06f %.06f %.06f %.06f\n" % (class_idx, xcen, ycen, w, h)) print(class_idx, xcen, ycen, w, h)
划分数据集:训练集和验证集
In [ ]:
#train_test_split 划分训练集验证集 import glob import random import os filelist = glob.glob('test_split/test_label/*.txt') #读取txt文件的路径 img_path = "test_split/train" #读取jpg文件的路径 test = random.sample(filelist, int(len(filelist)*0.2)) #划分比例 output_img_path = 'test_split/images/val' #验证集jpg输出路径 output_label_path = 'test_split/labels/val' #验证集labels输出路径 if not os.path.exists(output_img_path): os.makedirs(output_img_path) if not os.path.exists(output_label_path): os.makedirs(output_label_path) for file in test: filename = os.path.basename(file) img_filename = os.path.splitext(filename)[0] + '.jpg' txtpath = file impath = os.path.join(img_path, img_filename) out_text = os.path.join(output_label_path, os.path.basename(txtpath)) out_image = os.path.join(output_img_path, os.path.basename(impath)) print(txtpath,impath,out_text,out_image) os.system('mv ' + txtpath + ' ' + out_text) os.system('mv ' + impath + ' ' + out_image)
按照官方要求存放数据
--------- images \n
-----train
-----val
---------labels \n
-----train
-----val
进入 coco128.yaml 文件 修改文件路径、classes
进入train.py,找到def oarse_opt,修改:
(1)--weights yolov5l #可选择 yolov5s/yolov5m/yolov5l
(2)--data coco128.yaml #上面已经修改过
去终端 运行train.py
训练结束后,打开detect.py,修改:
(1)--weight参数,进入runs/train/exp/weights,用weight/best.pt替换
(2)--source参数,替换为测试集"images/test"路径
(3)--data参数,如果默认为coco128.yaml则无需修改
(4)修改txt输出的格式,与官方示例保持一致
In [1]:
save_txt_add_labels yolo的输出加标签 if save_txt: # Write to file xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist() # normalized xywh categories = ['Pedestrian', 'Cyclist', 'car', 'Truck', 'Tram' , 'Tricycle'] labels = categories[int(cls)] line = (cls, *xywh, conf) if save_conf else (cls, *xywh) # label format with open(f"{txt_path}.txt", "a") as f: f.write(("%g " * len(line)).rstrip() % line + labels + "\n")
Cell In[1], line 1 save_txt_add_labels yolo的输出加标签 ^ SyntaxError: invalid syntax
进入终端,运行python detect.py --save-txt
进入run/detect/exp/labels将.txt保存到官方指定文件夹中
In [ ]:
##任务二 1.数据标注:用官方给的.jpg数据导入labelme打标,输出.json格式 2.用批处理脚本将.json转换为datasets "yourDir=./" #.json文件路径 "outputDir=./" #输出文件路径
In [ ]:
#labelme_json_to_dataset_in_batch 任务二图像分割批量json转dataset setlocal set "yourDir=./" set "yourExt=*.json" set "outputDir=./" pushd %yourDir% for %%a in (%yourExt%) do ( labelme_json_to_dataset %%a -o "%outputDir%%%~na" ) popd endlocal
3.输出官方指定示例.png格式文件,存放在本地桌面
In [ ]:
linkcode
# dataset2mask import os import shutil def copy_and_rename_label_images(source_folder, dest_folder): # 检查目标文件夹是否存在,不存在则创建 if not os.path.exists(dest_folder): os.makedirs(dest_folder) # 遍历所有子文件夹 for root, dirs, files in os.walk(source_folder): for dir_name in dirs: subfolder_path = os.path.join(root, dir_name) label_image_path = os.path.join(subfolder_path, 'label.png') if os.path.exists(label_image_path): # 目标文件路径 dest_image_path = os.path.join(dest_folder, f"{dir_name}.png") # 复制文件并重命名 shutil.copy2(label_image_path, dest_image_path) print(f"Copied {label_image_path} to {dest_image_path}") if __name__ == "__main__": source_folder = 'D:\labelme\output' # 替换为json转出来的dataset文件路径 dest_folder = 'D:\labelme\output_mask' # 替换为目标文件夹路径 copy_and_rename_label_images(source_folder, dest_folder) # copy_and_rename_label_images('Json_dataset','mask_png')