目标检测实战(三):YOLO-Nano训练、测试、验证详细步骤

简介: 本文介绍了YOLO-Nano在目标检测中的训练、测试及验证步骤。YOLO-Nano是一个轻量级目标检测模型,使用ShuffleNet-v2作为主干网络,结合FPN+PAN特征金字塔和NanoDet的检测头。文章详细说明了训练前的准备、源代码下载、数据集准备、参数调整、模型测试、FPS测试、VOC-map测试、模型训练、模型测试和验证等步骤,旨在帮助开发者高效实现目标检测任务。

训练前准备

包括代码、数据集(VOC或者COCO)、调参等等…

下载源代码

受NanoDet启发的新版YOLO-Nano
网络架构分析:主干网:shufflenetv2,特征金字塔采用FPN+PAN,head用的是NanoDet的head

优化模型方式—多尺度学习、余弦退火、warmup、高分辨率、mosaic、KM聚类
损失函数:ciou_loss
预测框筛选:DIoU_nms

下载VOC和COCO数据集

这里给出一个公共数据集下载的网址:点击
修改数据集路径(voc0712.py的26行)

调参

这里主要是调整训练和epoch,no_warm_up选择False代表要采用预热模型的方式。
修改:
- epoch:config.py 里 5-8行
训练时设置use_cuda为True
训练时设置主干网的模型(yolo_nano_1.0x/yolo_nano_0.5x)
训练时设置dataset的类型VOC/COCO
如果要使用tensorboard则修改一下这里在这里插入图片描述
遇到的错误修改:
在这里插入图片描述

测试现有模式

测试图片检测和FPS

  • trained_model—修改为文件夹下存在的模型

自己根据评估那个写了个可以选择测试多张图片检测情况和FPS的代码,修改mode方式就可以。

import time
from PIL import Image
import cv2
import numpy as np
import os
import argparse
import torch
import torch.nn as nn
import torch.backends.cudnn as cudnn
from data import *
import numpy as np
import cv2
import tools
import time
from data.voc0712 import VOCAnnotationTransform

parser = argparse.ArgumentParser(description='YOLO-Nano Detection')
parser.add_argument('-v', '--version', default='yolo_nano_1.0x',
                    help='yolo_nano_0.5x, yolo_nano_1.0x.')
parser.add_argument('-d', '--dataset', default='voc',
                    help='voc, coco-val.')
parser.add_argument('-size', '--input_size', default=416, type=int,
                    help='input_size')
parser.add_argument('--trained_model',
                    default=r'weights/voc/yolo_nano_1.0x/yolo_nano_1.0x_67.23.pth',
                    type=str, help='Trained state_dict file path to open')
parser.add_argument('--conf_thresh', default=0.1, type=float,
                    help='Confidence threshold')
parser.add_argument('--nms_thresh', default=0.50, type=float,
                    help='NMS threshold')
parser.add_argument('--visual_threshold', default=0.3, type=float,
                    help='Final confidence threshold')
parser.add_argument('--cuda', action='store_true', default=True,
                    help='use cuda.')
parser.add_argument('--diou_nms', action='store_true', default=False,
                    help='use diou nms.')

args = parser.parse_args()

def vis(img, bboxes, scores, cls_inds, thresh, class_colors, class_names, class_indexs=None, dataset='voc'):
    if dataset == 'voc':
        for i, box in enumerate(bboxes):
            cls_indx = cls_inds[i]
            xmin, ymin, xmax, ymax = box
            if scores[i] > thresh:
                cv2.rectangle(img, (int(xmin), int(ymin)), (int(xmax), int(ymax)), class_colors[int(cls_indx)], 1)
                cv2.rectangle(img, (int(xmin), int(abs(ymin) - 20)), (int(xmax), int(ymin)),
                              class_colors[int(cls_indx)], -1)
                mess = '%s' % (class_names[int(cls_indx)])
                cv2.putText(img, mess, (int(xmin), int(ymin - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)

    elif dataset == 'coco-val' and class_indexs is not None:
        for i, box in enumerate(bboxes):
            cls_indx = cls_inds[i]
            xmin, ymin, xmax, ymax = box
            if scores[i] > thresh:
                cv2.rectangle(img, (int(xmin), int(ymin)), (int(xmax), int(ymax)), class_colors[int(cls_indx)], 1)
                cv2.rectangle(img, (int(xmin), int(abs(ymin) - 20)), (int(xmax), int(ymin)),
                              class_colors[int(cls_indx)], -1)
                cls_id = class_indexs[int(cls_indx)]
                cls_name = class_names[cls_id]
                # mess = '%s: %.3f' % (cls_name, scores[i])
                mess = '%s' % (cls_name)
                cv2.putText(img, mess, (int(xmin), int(ymin - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1)

    return img

def test(net, device, testset, transform, thresh, class_colors=None, class_names=None, class_indexs=None,
         dataset='voc',save=False,test_num=100,mode=''):
    num_images = len(testset)
    test_time,idx=[],1
    for index in range(num_images):
        print('Testing image {:d}/{:d}....'.format(index + 1, num_images))
        img, _ = testset.pull_image(index)
        img_tensor, _, h, w, offset, scale = testset.pull_item(index)

        # to tensor
        x = img_tensor.unsqueeze(0).to(device)

        t0 = time.time()
        # forward
        bboxes, scores, cls_inds = net(x)
        print("detection time used ", time.time() - t0, "s")
        if idx!=1:
            test_time.append(float(time.time() - t0))
        # scale each detection back up to the image
        max_line = max(h, w)
        # map the boxes to input image with zero padding
        bboxes *= max_line
        # map to the image without zero padding
        bboxes -= (offset * max_line)

        img_processed = vis(img, bboxes, scores, cls_inds, thresh, class_colors, class_names, class_indexs, dataset)
        if mode=='fps':
            if idx == test_num:
                break
            idx += 1
        else:
            cv2.imshow('detection', img_processed)
            cv2.waitKey(0)
            if save:
                print('Saving the' + str(index) + '-th image ...')
                save_path=r'D:\pycharm_Z\YOLO-Nano\img_files\save_detection_pic/'
                os.makedirs(os.path.dirname(save_path),exist_ok=True)
                cv2.imwrite( save_path+ str(index).zfill(6) +'.jpg', img_processed)
    return test_time

if __name__ == '__main__':
    # get device
    if args.cuda:
        print('use cuda')
        cudnn.benchmark = True
        device = torch.device("cuda")
    else:
        device = torch.device("cpu")

    input_size = [args.input_size, args.input_size]

    # dataset
    if args.dataset == 'voc':
        print('test on voc ...')
        class_names = VOC_CLASSES
        class_indexs = None
        num_classes = 20
        anchor_size = MULTI_ANCHOR_SIZE
        dataset = VOCDetection(root=VOC_ROOT,
                               img_size=None,
                               image_sets=[('2007', 'test')],
                               transform=BaseTransform(input_size))

    elif args.dataset == 'coco-val':
        print('test on coco-val ...')
        class_names = coco_class_labels
        class_indexs = coco_class_index
        num_classes = 80
        anchor_size = MULTI_ANCHOR_SIZE_COCO
        dataset = COCODataset(
            data_dir=coco_root,
            json_file='instances_val2017.json',
            name='val2017',
            transform=BaseTransform(input_size),
            img_size=input_size[0])

    class_colors = [(np.random.randint(255), np.random.randint(255), np.random.randint(255)) for _ in
                    range(num_classes)]

    # build model
    if args.version == 'yolo_nano_0.5x':
        from models.yolo_nano import YOLONano

        backbone = '0.5x'
        net = YOLONano(device, input_size=input_size, num_classes=num_classes, anchor_size=anchor_size,
                       backbone=backbone)
        print('Let us train yolo_nano_0.5x ......')

    if args.version == 'yolo_nano_1.0x':
        from models.yolo_nano import YOLONano

        backbone = '1.0x'
        net = YOLONano(device, input_size=input_size, num_classes=num_classes, anchor_size=anchor_size,
                       backbone=backbone)
        print('Let us train yolo_nano_1.0x ......')

    else:
        print('Unknown version !!!')
        exit()

    net.load_state_dict(torch.load(args.trained_model, map_location=device))
    net.to(device).eval()

    print('Finished loading model!')
    #-------------------------------------------------------------------------#
    #   mode用于指定测试的模式:
    #   'predict'表示 多张图片预测和保存
    #   'fps'表示测试fps
    #-------------------------------------------------------------------------#
    mode = "predict"

    if mode == "predict":
        # evaluation
        test(net=net,
             device=device,
             testset=dataset,
             transform=BaseTransform(input_size),
             thresh=args.visual_threshold,
             class_colors=class_colors,
             class_names=class_names,
             class_indexs=class_indexs,
             dataset=args.dataset,
             save=True,
             mode="predict"
             )

    elif mode == "fps":
        # evaluation
        test_num=10
        time_all=test(net=net,
             device=device,
             testset=dataset,
             transform=BaseTransform(input_size),
             thresh=args.visual_threshold,
             class_colors=class_colors,
             class_names=class_names,
             class_indexs=class_indexs,
             dataset=args.dataset,
             test_num=test_num,
             mode="fps"
             )
        time_avg=sum(time_all)/len(time_all)
        print('the whole time:{}'.format(time_avg))
        print('fps:{}'.format(1/time_avg))

测试VOC-map

找到eval.py并修改测试模型路径和指定数据集路径
在这里插入图片描述
在这里插入图片描述
然后就可以运行eval.py文件。

!!!!如果遇到错误R = [obj for obj in recs[imagename] if obj[‘name’] == classname] KeyError: ‘007765’
解决办法------训练前需要将cache中的pki文件(找到voc_eval/test)以及VOCdevkit2007中annotations_cache的缓存删掉(在你的数据集里面会新建这个文件)

开始训练模型

训练文件脚本:train.py
修改完上述的地方应该就可以直接运行了(环境没问题的情况下)
在这里插入图片描述
每10个epoch会测试一下map
如果使用了tensorboard,可以在终端输入
tensorboard --logdir=D:\pycharm_Z\YOLO-Nano\log\voc\yolo_nano_1.0x\2021-09-13-13-31-02
出现一个网址进去就是
在这里插入图片描述
一个为分类loss,一个为回归loss,一个为多目标loss

测试模型

测试模型就可以使用我上面给出的代码,检测一下fps和图片检测情况
在这里插入图片描述
在这里插入图片描述

验证模型

如果是VOC数据集
验证模型的指标为Map,以及各类AP情况,通过eval.py,将模型改为你训练后的模型即可
如果是COCO数据集同理

目录
相关文章
|
25天前
|
测试技术 持续交付 UED
软件测试的艺术:确保质量的实战策略
在软件开发的舞台上,测试是那把确保每个功能如交响乐般和谐奏响的指挥棒。本文将深入探讨软件测试的重要性、基本类型以及如何设计高效的测试策略。我们将通过一个实际的代码示例,展示如何运用这些策略来提升软件质量和用户体验。
|
1天前
|
算法 数据挖掘 测试技术
犬类癌症检测(CANDiD)研究:使用独立测试集对1000多只犬进行基于高通量测序的多癌种早期检测"液体活检"血液测试的临床验证
这项研究首次在大规模独立测试集上验证了基于NGS的液体活检在犬类多癌种检测中的应用。该方法具有很高的特异性,可以作为一种新的无创癌症筛查和辅助诊断工具。通过早期发现癌症,有望改善犬类癌症的诊断和管理模式。
26 12
|
24天前
|
JavaScript 安全 编译器
TypeScript 与 Jest 测试框架的结合使用,从 TypeScript 的测试需求出发,介绍了 Jest 的特点及其与 TypeScript 结合的优势,详细讲解了基本测试步骤、常见测试场景及异步操作测试方法
本文深入探讨了 TypeScript 与 Jest 测试框架的结合使用,从 TypeScript 的测试需求出发,介绍了 Jest 的特点及其与 TypeScript 结合的优势,详细讲解了基本测试步骤、常见测试场景及异步操作测试方法,并通过实际案例展示了其在项目中的应用效果,旨在提升代码质量和开发效率。
37 6
|
28天前
|
敏捷开发 安全 测试技术
掌握单元测试:确保代码质量的关键步骤
单元测试是确保代码质量、提升可维护性和可靠性的重要手段。本文介绍了单元测试的基本概念、重要性及最佳实践,包括测试驱动开发(TDD)、保持测试独立性、使用断言库和模拟依赖等,旨在帮助开发者掌握单元测试技巧,提高开发效率。
|
1月前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
60 3
|
1月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
52 1
|
1月前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
57 2
|
1月前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
40 2
|
2月前
|
机器学习/深度学习 监控 计算机视觉
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
本文介绍了如何使用YOLOv7进行目标检测,包括环境搭建、数据集准备、模型训练、验证、测试以及常见错误的解决方法。YOLOv7以其高效性能和准确率在目标检测领域受到关注,适用于自动驾驶、安防监控等场景。文中提供了源码和论文链接,以及详细的步骤说明,适合深度学习实践者参考。
508 0
目标检测实战(八): 使用YOLOv7完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
2月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
73 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)