摘要

YoloV6出来没有多久,YoloV7就开始流行了。如今的Yolo系列的模型都是沿用了YoloV3的架构,大家都是在卷积上做了一些更改。Yolov6和Yolov7都加入了Rep的结构。如图:

图片来自:https://zhuanlan.zhihu.com/p/543743278
YOLOv7 在 5 FPS 到 160 FPS 范围内的速度和准确度都超过了所有已知的物体检测器,并且在 GPU V100 上 30 FPS 或更高的所有已知实时物体检测器中具有最高的准确度 56.8% AP。
论文翻译:https://wanghao.blog.csdn.net/article/details/126302859
代码:https://github.com/WongKinYiu/yolov7
论文链接:https://arxiv.org/abs/2207.02696
今天我们一起学习如何使用YoloV7训练自己的数据集

数据集

数据集是我自己标注的飞机数据集,下载地址:
https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/63242994。
总共32种飞机:
[‘c17’, ‘c5’, ‘helicopter’, ‘c130’, ‘f16’, ‘b2’, ‘other’, ‘b52’, ‘kc10’, ‘command’, ‘f15’, ‘kc135’, ‘a10’, ‘b1’, ‘aew’, ‘f22’, ‘p3’, ‘p8’, ‘f35’, ‘f18’, ‘v22’, ‘f4’, ‘globalhawk’, ‘u2’, ‘su-27’, ‘il-38’, ‘tu-134’, ‘su-33’, ‘an-70’, ‘su-24’, ‘tu-22’, ‘il-76’]
接下来是如何制作yolov6数据集,yolov6使用的数据集格式和yolov5一样。如图:

格式:类别,中心点x,中心点y,w,h。
新建脚本make_yolo_data.py,插入代码:

import osimport shutilimport numpy as npimport jsonfrom glob import globimport cv2from sklearn.model_selection import train_test_splitfrom os import getcwddef convert(size, box):    dw = 1. / (size[0])    dh = 1. / (size[1])    x = (box[0] + box[1]) / 2.0 - 1    y = (box[2] + box[3]) / 2.0 - 1    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 change_2_yolo5(files, txt_Name):    imag_name=[]    for json_file_ in files:        json_filename = labelme_path + json_file_ + ".json"        out_file = open('%s/%s.txt' % (labelme_path, json_file_), 'w')        json_file = json.load(open(json_filename, "r", encoding="utf-8"))        # image_path = labelme_path + json_file['imagePath']        imag_name.append(json_file_+'.jpg')        height, width, channels = cv2.imread(labelme_path + json_file_ + ".jpg").shape        for multi in json_file["shapes"]:            points = np.array(multi["points"])            xmin = min(points[:, 0]) if min(points[:, 0]) > 0 else 0            xmax = max(points[:, 0]) if max(points[:, 0]) > 0 else 0            ymin = min(points[:, 1]) if min(points[:, 1]) > 0 else 0            ymax = max(points[:, 1]) if max(points[:, 1]) > 0 else 0            label = multi["label"].lower()            if xmax <= xmin:                pass            elif ymax <= ymin:                pass            else:                cls_id = classes.index(label)                b = (float(xmin), float(xmax), float(ymin), float(ymax))                bb = convert((width, height), b)                out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')                # print(json_filename, xmin, ymin, xmax, ymax, cls_id)    return imag_namedef image_txt_copy(files,scr_path,dst_img_path,dst_txt_path):    """    :param files: 图片名字组成的list    :param scr_path: 图片的路径    :param dst_img_path: 图片复制到的路径    :param dst_txt_path: 图片对应的txt复制到的路径    :return:    """    for file in files:        img_path=scr_path+file        print(file)        shutil.copy(img_path, dst_img_path+file)        scr_txt_path=scr_path+file.split('.')[0]+'.txt'        shutil.copy(scr_txt_path, dst_txt_path + file.split('.')[0]+'.txt')if __name__ == '__main__':    classes = ['c17', 'c5', 'helicopter', 'c130', 'f16', 'b2',    'other', 'b52', 'kc10', 'command', 'f15', 'kc135', 'a10',    'b1', 'aew', 'f22', 'p3', 'p8', 'f35', 'f18', 'v22', 'f4',    'globalhawk', 'u2', 'su-27', 'il-38', 'tu-134', 'su-33',    'an-70', 'su-24', 'tu-22', 'il-76']    # 1.标签路径    labelme_path = "USA-Labelme/"    isUseTest = True  # 是否创建test集    # 3.获取待处理文件    files = glob(labelme_path + "*.json")    files = [i.replace("\\", "/").split("/")[-1].split(".json")[0] for i in files]    for i in files:        print(i)    trainval_files, test_files = train_test_split(files, test_size=0.1, random_state=55)    # split    train_files, val_files = train_test_split(trainval_files, test_size=0.1, random_state=55)    train_name_list=change_2_yolo5(train_files, "train")    print(train_name_list)    val_name_list=change_2_yolo5(val_files, "val")    test_name_list=change_2_yolo5(test_files, "test")    #创建数据集文件夹。    file_List = ["train", "val", "test"]    for file in file_List:        if not os.path.exists('./VOC/images/%s' % file):            os.makedirs('./VOC/images/%s' % file)        if not os.path.exists('./VOC/labels/%s' % file):            os.makedirs('./VOC/labels/%s' % file)    image_txt_copy(train_name_list,labelme_path,'./VOC/images/train/','./VOC/labels/train/')    image_txt_copy(val_name_list, labelme_path, './VOC/images/val/', './VOC/labels/val/')    image_txt_copy(test_name_list, labelme_path, './VOC/images/test/', './VOC/labels/test/')

转换完成后就可以得到用于训练的数据集了,如下图:

核心思路:
第一步 使用train_test_split方法切分出训练集、验证集和测试集。
第二步 调用change_2_yolo5方法将json里面的数据转为yolov5格式的txt数据,返回训练集、验证集和测试集的图片list。
第三步 创建数据集文件夹,然后将图片和txt文件copy到对应的目录下面。
接下来就开始训练了

训练

有了数据集就可以开始训练了。下载yolov7的代码,将其解压到指定的位置,然后将数据集复制到yolov7的根目录。如下图:

然后下载yolov7的权重,下载地址:
https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7.pt
如果下载中断可以使用迅雷下载。
下载完成后放在YoloV7项目的根目录。
在data目录增加VOC.yaml

在里面填写如下内容:

# Please insure that your custom_dataset are put in same parent dir with YOLOv7_DIRtrain: ./VOC/images/train # train imagesval: VOC/images/val # val imagestest: VOC/images/test # test images (optional)# whether it is coco dataset, only coco dataset should be set to True.is_coco: False# Classesnc: 32  # number of classesnames: ['c17', 'c5', 'helicopter', 'c130', 'f16', 'b2',    'other', 'b52', 'kc10', 'command', 'f15', 'kc135', 'a10',    'b1', 'aew', 'f22', 'p3', 'p8', 'f35', 'f18', 'v22', 'f4',    'globalhawk', 'u2', 'su-27', 'il-38', 'tu-134', 'su-33',    'an-70', 'su-24', 'tu-22', 'il-76']

修改train.py里面的参数

    parser.add_argument('--weights', type=str, default='yolov7.pt', help='initial weights path')    parser.add_argument('--cfg', type=str, default='cfg/training/yolov7.yaml', help='model.yaml path')    parser.add_argument('--data', type=str, default='data/VOC.yaml', help='data.yaml path')    parser.add_argument('--epochs', type=int, default=300)    parser.add_argument('--batch-size', type=int, default=4, help='total batch size for all GPUs')    parser.add_argument('--workers', type=int, default=0, help='maximum number of dataloader workers')

weights:权重文件。
cfg:yolov7模型配置文件。
data:数据配置文件
workers:在win系统下面设置为0,否则报错。

上面修改了,检查一下环境配置是否正确,依赖包是否都安装了。

# Usage: pip install -r requirements.txt# Base ----------------------------------------matplotlib>=3.2.2numpy>=1.18.5opencv-python>=4.1.1Pillow>=7.1.2PyYAML>=5.3.1requests>=2.23.0scipy>=1.4.1torch>=1.7.0,!=1.12.0torchvision>=0.8.1,!=0.13.0tqdm>=4.41.0protobuf<4.21.3# Logging -------------------------------------tensorboard>=2.4.1# wandb# Plotting ------------------------------------pandas>=1.1.4seaborn>=0.11.0# Export --------------------------------------# coremltools>=4.1  # CoreML export# onnx>=1.9.0  # ONNX export# onnx-simplifier>=0.3.6  # ONNX simplifier# scikit-learn==0.19.2  # CoreML quantization# tensorflow>=2.4.1  # TFLite export# tensorflowjs>=3.9.0  # TF.js export# openvino-dev  # OpenVINO export# Extras --------------------------------------ipython  # interactive notebookpsutil  # system utilizationthop  # FLOPs computation# albumentations>=1.0.3# pycocotools>=2.0  # COCO mAP# roboflow

如果没有问题就可以开始训练,如下图:


等待训练完成后就可以才是测试了。

测试

测试使用detect.py脚本文件

    parser.add_argument('--weights', nargs='+', type=str, default='runs/train/exp9/weights/best.pt', help='model.pt path(s)')    parser.add_argument('--source', type=str, default='inference/images', help='source')  # file/folder, 0 for webcam    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')    parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')    parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')    parser.add_argument('--device', default='0', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')

weights:训练好的模型路径
source:测试图片的路径。
img-size:图片输入的大小。
conf-thres:置信度的下线。
iou-thres:IOU的阈值
device:GPU的编号,或者设置为cpu。
然后就可以运行detect.py脚本了。
测试结果:

完整代码

https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/86749406