• YOLOv5从训练到移植


    一、图像采集和标注

    • 图像采集

    覆盖所有的数据目标,不同场景(视角、光照、可能的干扰)、距离、运动、背景等,用深度和广度摄像头都行。

    若兼顾效率和准确率,可以用迁移学习思路训练,则不同场景下采集的图像数据量可以适当降低,但避免场景单一问题。

    • 图像标注

    可以看LabelImg安装与使用

    二、YOLOv5模型训练

    1、YOLOv5深度网络下载

    下载地址:YOLOv5模型

    2、安装环境依赖库

    安装命令语句 

    pip install -r requirements.txt

     或者

    按照requirements.txt文件里依赖库的顺序,分别用pip install安装对应的包

    3、准备数据集

    把图像数据集和标定数据复制到yolov5/InsectImg/RawInsect文件夹下, 创建一个YOLOLabels文件夹,主要将Pascal VOC标注模式生成的.xml文件转换为.txt格式。

    完整代码

    1. import xml.etree.ElementTree as ET
    2. import pickle
    3. import os
    4. from os import listdir, getcwd
    5. from os.path import join
    6. import random
    7. from shutil import copyfile
    8. classes = ['aedes', 'aegypti','albiceps','albopictus','americana','australasiae','bazini','cheopis','coquillett', 'culex','cuprina',
    9. 'fabricius','fuliginosa','gblattella','melanura', 'musca','pattoni','rhombifolia','sericata','sorbens','wiedemann']
    10. TRAIN_RATIO = 80
    11. def clear_hidden_files(path):
    12. dir_list = os.listdir(path)
    13. for i in dir_list:
    14. abspath = os.path.join(os.path.abspath(path), i)
    15. if os.path.isfile(abspath):
    16. if i.startswith("._"):
    17. os.remove(abspath)
    18. else:
    19. clear_hidden_files(abspath)
    20. def convert(size, box):
    21. dw = 1. / size[0]
    22. dh = 1. / size[1]
    23. x = (box[0] + box[1]) / 2.0
    24. y = (box[2] + box[3]) / 2.0
    25. w = box[1] - box[0]
    26. h = box[3] - box[2]
    27. x = x * dw
    28. w = w * dw
    29. y = y * dh
    30. h = h * dh
    31. return (x, y, w, h)
    32. def convert_annotation(image_id):
    33. in_file = open('InsectImg/RawInsect/Annotations/%s.xml' % image_id)
    34. out_file = open('InsectImg/RawInsect/YOLOLabels/%s.txt' % image_id, 'w')
    35. tree = ET.parse(in_file)
    36. root = tree.getroot()
    37. size = root.find('size')
    38. w = int(size.find('width').text)
    39. h = int(size.find('height').text)
    40. for obj in root.iter('object'):
    41. difficult = obj.find('difficult').text
    42. cls = obj.find('name').text
    43. if cls not in classes or int(difficult) == 1:
    44. continue
    45. cls_id = classes.index(cls)
    46. xmlbox = obj.find('bndbox')
    47. b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
    48. float(xmlbox.find('ymax').text))
    49. bb = convert((w, h), b)
    50. out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
    51. in_file.close()
    52. out_file.close()
    53. wd = os.getcwd()
    54. wd = os.getcwd()
    55. data_base_dir = os.path.join(wd, "InsectImg/")
    56. if not os.path.isdir(data_base_dir):
    57. os.mkdir(data_base_dir)
    58. work_sapce_dir = os.path.join(data_base_dir, "RawInsect/")
    59. if not os.path.isdir(work_sapce_dir):
    60. os.mkdir(work_sapce_dir)
    61. annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
    62. if not os.path.isdir(annotation_dir):
    63. os.mkdir(annotation_dir)
    64. clear_hidden_files(annotation_dir)
    65. image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
    66. if not os.path.isdir(image_dir):
    67. os.mkdir(image_dir)
    68. clear_hidden_files(image_dir)
    69. yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
    70. if not os.path.isdir(yolo_labels_dir):
    71. os.mkdir(yolo_labels_dir)
    72. clear_hidden_files(yolo_labels_dir)
    73. yolov5_images_dir = os.path.join(data_base_dir, "images/")
    74. if not os.path.isdir(yolov5_images_dir):
    75. os.mkdir(yolov5_images_dir)
    76. clear_hidden_files(yolov5_images_dir)
    77. yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
    78. if not os.path.isdir(yolov5_labels_dir):
    79. os.mkdir(yolov5_labels_dir)
    80. clear_hidden_files(yolov5_labels_dir)
    81. yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
    82. if not os.path.isdir(yolov5_images_train_dir):
    83. os.mkdir(yolov5_images_train_dir)
    84. clear_hidden_files(yolov5_images_train_dir)
    85. yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
    86. if not os.path.isdir(yolov5_images_test_dir):
    87. os.mkdir(yolov5_images_test_dir)
    88. clear_hidden_files(yolov5_images_test_dir)
    89. yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
    90. if not os.path.isdir(yolov5_labels_train_dir):
    91. os.mkdir(yolov5_labels_train_dir)
    92. clear_hidden_files(yolov5_labels_train_dir)
    93. yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
    94. if not os.path.isdir(yolov5_labels_test_dir):
    95. os.mkdir(yolov5_labels_test_dir)
    96. clear_hidden_files(yolov5_labels_test_dir)
    97. train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
    98. test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
    99. train_file.close()
    100. test_file.close()
    101. train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
    102. test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
    103. list_imgs = os.listdir(image_dir) # list image files
    104. prob = random.randint(1, 100)
    105. print("Probability: %d" % prob)
    106. for i in range(0, len(list_imgs)):
    107. path = os.path.join(image_dir, list_imgs[i])
    108. if os.path.isfile(path):
    109. image_path = image_dir + list_imgs[i]
    110. voc_path = list_imgs[i]
    111. (nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))
    112. (voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))
    113. annotation_name = nameWithoutExtention + '.xml'
    114. annotation_path = os.path.join(annotation_dir, annotation_name)
    115. label_name = nameWithoutExtention + '.txt'
    116. label_path = os.path.join(yolo_labels_dir, label_name)
    117. prob = random.randint(1, 100)
    118. print("Probability: %d" % prob)
    119. if (prob < TRAIN_RATIO): # train dataset
    120. if os.path.exists(annotation_path):
    121. train_file.write(image_path + '\n')
    122. convert_annotation(nameWithoutExtention) # convert label
    123. copyfile(image_path, yolov5_images_train_dir + voc_path)
    124. copyfile(label_path, yolov5_labels_train_dir + label_name)
    125. else: # test dataset
    126. if os.path.exists(annotation_path):
    127. test_file.write(image_path + '\n')
    128. convert_annotation(nameWithoutExtention) # convert label
    129. copyfile(image_path, yolov5_images_test_dir + voc_path)
    130. copyfile(label_path, yolov5_labels_test_dir + label_name)
    131. train_file.close()
    132. test_file.close()
    • 修改class类别标签名
    • 修改TRAIN_RATIO,划分训练数据集和验证数据集比例8:2
    • 修改文件路径

    第一处:

    1. in_file = open('InsectImg/RawInsect/Annotations/%s.xml' % image_id)
    2. out_file = open('InsectImg/RawInsect/YOLOLabels/%s.txt' % image_id, 'w')

    第二处:

    1. data_base_dir = os.path.join(wd, "InsectImg/")
    2. if not os.path.isdir(data_base_dir):
    3. os.mkdir(data_base_dir)
    4. work_sapce_dir = os.path.join(data_base_dir, "RawInsect/")

     4、配置YOLOv5数据环境

    data文件夹下,仿照coco.yaml,创建insect.yaml文件

    • 修改train训练数据集路径
    • 修改val验证数据集路径
    • 修改nc类别数
    • 修改names列表标签名

     在models文件夹下,仿照yolov5l.yaml,创建yolov5l_insect.yaml文件

    • 修改nc类别数

    weights文件夹下,存放从GitHub上下载的yolov5l6.pt

    注意:如果YOLOv5系列有n、s、m、l、x,models文件夹下创建什么类型的模型,weights文件夹下要存放相应的训练好的模型pt文件。

    5、修改train.py参数

    一般情况下,需要修改参数: 

    • 修改 --weights路径
    • 修改--cfg配置模型路径
    • 修改--data图像数据路径
    • 根据电脑GPU核,设置--batch-size
    • 根据n、s、m、l、x,设置--imgsz,YOLOv5l输入图像大小设置为640
    • 一般--resume设置为False,如果因电脑重启导致训练中断,可以设置为True,接着上一次的结果继续训练
    • epochs一般300,也可以根据训练情况调整

    其他参数可以根据情况自动设置

    6、运行train.py 进行模型训练

    训练模型结果保存在路径

    E:\Code\Python\yolov5\runs\train\exp

    该路径下的weights文件夹生成了last.pt和best.pt两个文件,选择best.pt作为移植模型。

    三、YOLOv5模型移植

    1、修改export.py文件

    • 修改--data,为自己数据的.yaml文件
    • 修改--weights,为上一步YOLOv5l训练得到best.pt最佳路径
    • 修改--imgsz,一般设置为320
    • 修改--include,根据实际案例,可以选择tflite/onnx/pb等。

    运行export.py导出量化后的模型

    2、量化后模型移植终端

    配置终端环境,调用量化后的模型。

  • 相关阅读:
    和xshell和crt说再见,认识了一款51k star多端跨平台终端神器,强大酷炫
    u盘被格式化了文件还可以恢复吗?
    【附源码】计算机毕业设计JAVA幼儿健康管理系统
    Linux生成随机密码和根据密码批量生成用户
    47.Java线程
    9.30小任务
    20.ROS编程学习:通信的各种进阶使用python
    消息队列中间件的选型与比较
    【STM32】入门(三):按键使用-GPIO端口输出控制
    如何合并为pdf文件?合并为pdf文件的方法
  • 原文地址:https://blog.csdn.net/miao0967020148/article/details/130859792