计算机视觉课设--基于YOLOv5的目标检测系统

目录
第一章 项目介绍…3
1.1项目简介…3
1.2需求解读…3
1.3 YOLOv5算法在目标检测中的应用…3
第二章YOLOv5算法介绍…4
2.1 YOLOv5算法简介…4
2.2 YOLOv5算法详解…4
2.2.1 YOLOv5网络架构…4
2.3 YOLOv5实现细节…5
2.3.1 YOLOv5基础组件…5
2.4 输入端改进…5
2.5基准网络…6
2.6 Neck网络…7
2.7 输出端…7
第三章 实现流程…8
3.1 pytorch 框架平台介绍…8
3.1.1 pytorch的简介…8
3.1.2 pytorch 包含的内容…8
3.1.2.1overview…8
3.1.2.2 自定义 Module…9
3.1.3pytorch的三大优势…9
3.2 模型、数据库准备及复现…9
3.2.1 下载Yolov5…9
3.2.2 下载数据库…9
3.2.3复现…10
3.2.3.1 数据集配置文件…10
3.2.3.2 模型配置文件…10
3.2.3.3 训练模型…11
3.2.3.4. 目标检测…11
3.3 操作流程图…12
3.4项目结果…13
第四章 代码…14
第五章 学习心得…19
参考文献…20
第一章项目介绍
1.1 项目简介
该项目是基于YOLOv5算法的目标检测实现。该项目是为了检测王者荣耀画面里各个事物,包括游戏中的英雄,塔,精灵等事物。首先,在github下载yolov5的文件,准备数据集。然后,利用自己的数据训练适用于自己数据的模型。最后将自己的游戏截图或者录屏利用自己训练好的模型进行目标检测。整个项目下来,学习到了实现目标检测每一步是如何实现的,目的是什么,结果是什么。最重要的是,能够实现代码跑通,将这个项目能够得到实现。
1.2需求解读
YOLOV4出现之后不久,YOLOv5横空出世。YOLOv5在YOLOv4算法的基础上做了进一步的改进,检测性能得到进一步的提升。虽然YOLOv5算法并没有与YOLOv4算法进行性能比较与分析,但是YOLOv5在COCO数据集上面的测试效果还是挺不错的。大家对YOLOv5算法的创新性半信半疑,有的人对其持肯定态度,有的人对其持否定态度。在我看来,YOLOv5检测算法中还是存在很多可以学习的地方,虽然这些改进思路看来比较简单或者创新点不足,但是它们确定可以提升检测算法的性能。其实工业界往往更喜欢使用这些方法,而不是利用一个超级复杂的算法来获得较高的检测精度。本文将对YOLOv5检测算法中提出的改进思路进行详细的解说,大家可以尝试者将这些改进思路应用到其它的目标检测算法中。
1.3 YOLOv5算法在目标检测中的应用
YOLO 的思路起源于将基本的CNN思路从分类任务扩展到检测中,2020 年 6 月10日YOLOv5发布。 Yolov5官方代码中,给出的目标检测网络中一共有4个版本,分别是Yolov5s、Yolov5m、Yolov5l、Yolov5x四个模型。他们公布的结果表明,YOLOv5 的表现要优于谷歌开源的目标检测框架 EfficientDet,尽管 YOLOv5 的开发者没有明确地将其与 YOLOv4 进行比较,但他们却声称 YOLOv5 能在 Tesla P100 上实现 140 FPS 的快速检测;相较而言,YOLOv4 的基准结果是在 50 FPS 速度下得到的。总结起来,YOLOv5 宣称自己速度非常快,有非常轻量级的模型大小,同时在准确度方面又与 YOLOv4 基准相当。由此,YOLOv5算法在目标检测中
近几年,基于yolov5算法在目标检测中的运用在我们生活中随处可见,比如,在建筑业行业中,有基于YOLOv5的安全帽佩戴检测方法,在道路目标检测与识别在当前自动驾驶领域中,基于YOLOv5算法的道路场景目标检测应用研究,在遥感图像处理领域中,有基于YOLOv5的遥感图像目标检测研究等等。
YOLOv5算法在实际应用中,准确性较高,比如分割后的小图,再输入目标检测网络中,对于最小目标像素的下限会大大降低。其次在应用中,比如遥感图像,或者无人机图像,如果无需考虑实时性的检测,且对小目标检测也有需求的项目,可以尝试此种方式。但是,YOLOv5也有其缺点,增加计算量,比如原本7680*2160的图像,如果使用直接大图检测的方式,一次即可检测完。
第二章YOLOv5算法介绍
2.1 YOLOv5算法简介
YOLOv5是一种单阶段目标检测算法,该算法在YOLOv4的基础上添加了一些新的改进思路,使其速度与精度都得到了极大的性能提升。主要的改进思路如下所示:
(1)输入端:在模型训练阶段,提出了一些改进思路,主要包括Mosaic数据增强、自适应锚框计算、自适应图片缩放;
(2)基准网络:融合其它检测算法中的一些新思路,主要包括:Focus结构与CSP结构;
(3)Neck网络:目标检测网络在BackBone与最后的Head输出层之间往往会插入一些层,Yolov5中添加了FPN+PAN结构;
(4)Head输出层:输出层的锚框机制与YOLOv4相同,主要改进的是训练时的损失函数GIOU_Loss,以及预测框筛选的DIOU_nms。
2.2 YOLOv5算法详解
2.2.1 YOLOv5网络架构
在这里插入图片描述

上图展示了YOLOv5目标检测算法的整体框图。对于一个目标检测算法而言,我们通常可以将其划分为4个通用的模块,具体包括:输入端、基准网络、Neck网络与Head输出端,对应于上图中的4个红色模块。YOLOv5算法具有4个版本,具体包括:YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x四种。
输入端-输入端表示输入的图片。该网络的输入图像大小为608608,该阶段通常包含一个图像预处理阶段,即将输入图像缩放到网络的输入大小,并进行归一化等操作。在网络训练阶段,YOLOv5使用Mosaic数据增强操作提升模型的训练速度和网络的精度;并提出了一种自适应锚框计算与自适应图片缩放方法。
基准网络-基准网络通常是一些性能优异的分类器种的网络,该模块用来提取一些通用的特征表示。YOLOv5中不仅使用了CSPDarknet53结构,而且使用了Focus结构作为基准网络。
Neck网络-Neck网络通常位于基准网络和头网络的中间位置,利用它可以进一步提升特征的多样性及鲁棒性。虽然YOLOv5同样用到了SPP模块、FPN+PAN模块,但是实现的细节有些不同。
Head输出端-Head用来完成目标检测结果的输出。针对不同的检测算法,输出端的分支个数不尽相同,通常包含一个分类分支和一个回归分支。YOLOv4利用GIOU_Loss来代替Smooth L1 Loss函数,从而进一步提升算法的检测精度。
2.3 YOLOv5实现细节
2.3.1 YOLOv5基础组件
CBL-CBL模块由Conv+BN+Leaky_relu激活函数组成,如上图中的模块1所示。
Res unit-借鉴ResNet网络中的残差结构,用来构建深层网络,CBM是残差模块中的子模块,如上图中的模块2所示。
CSP1_X-借鉴CSPNet网络结构,该模块由CBL模块、Res unint模块以及卷积层、Concate组成而成,如上图中的模块3所示。
CSP2_X-借鉴CSPNet网络结构,该模块由卷积层和X个Res unint模块Concate组成而成,如上图中的模块4所示。
Focus-如上图中的模块5所示,Focus结构首先将多个slice结果Concat起来,然后将其送入CBL模块中。
SPP-采用1×1、5×5、9×9和13×13的最大池化方式,进行多尺度特征融合,如上图中的模块6所示。
2.4 输入端改进
Mosaic数据增强
YOLOv5中在训练模型阶段仍然使用了Mosaic数据增强方法,该算法是在CutMix数据增强方法的基础上改进而来的。CutMix仅仅利用了两张图片进行拼接,而Mosaic数据增强方法则采用了4张图片,并且按照随机缩放、随机裁剪和随机排布的方式进行拼接而成,具体的效果如下图所示。这种增强方法可以将几张图片组合成一张,这样不仅可以丰富数据集的同时极大的提升网络的训练速度,而且可以降低模型的内存需求。
自适应锚框计算
在YOLO系列算法中,针对不同的数据集,都需要设定特定长宽的锚点框。在网络训练阶段,模型在初始锚点框的基础上输出对应的预测框,计算其与GT框之间的差距,并执行反向更新操作,从而更新整个网络的参数,因此设定初始锚点框也是比较关键的一环。在YOLOv3和YOLOv4检测算法中,训练不同的数据集时,都是通过单独的程序运行来获得初始锚点框。YOLOv5中将此功能嵌入到代码中,每次训练时,根据数据集的名称自适应的计算出最佳的锚点框,用户可以根据自己的需求将功能关闭或者打开,具体的指令为parser.add_argument(’–noautoanchor’, action=‘store_ true’, help=‘disable autoanchor check’),如果需要打开,只需要在训练代码时增加–noautoanch or选项即可。
自适应图片缩放
针对不同的目标检测算法而言,我们通常需要执行图片缩放操作,即将原始的输入图片缩放到一个固定的尺寸,再将其送入检测网络中。YOLO系列算法中常用的尺寸包括416
416,608 608等尺寸。原始的缩放方法存在着一些问题,由于在实际的使用中的很多图片的长宽比不同,因此缩放填充之后,两端的黑边大小都不相同,然而如果填充的过多,则会存在大量的信息冗余,从而影响整个算法的推理速度。为了进一步提升YOLOv5算法的推理速度,该算法提出一种方法能够自适应的添加最少的黑边到缩放之后的图片中。
需要注意的是:(1)该操作仅在模型推理阶段执行,模型训练阶段仍然和传统的方法相同,将原始图片裁剪到416
416大小;(2)YOLOv3与YOLOv4中默认填充的数值是(0,0,0),而YOLOv5中默认填充的数值是(114,114,114);(3)该操作仅仅针对原始图片的短边而言,仍然将长边裁剪到416。
2.5基准网络
Focus结构-该结构的主要思想是通过slice操作来对输入图片进行裁剪。如下图所示,原始输入图片大小为6086083,经过Slice与Concat操作之后输出一个30430412的特征映射;接着经过一个通道个数为32的Conv层(该通道个数仅仅针对的是YOLOv5s结构,其它结构会有相应的变化),输出一个30430432大小的特征映射。
在这里插入图片描述

YOLOv4网络结构中,借鉴了CSPNet的设计思路,仅仅在主干网络中设计了CSP结构。而YOLOv5中设计了两种CSP结构,以YOLOv5s网络为例,CSP1_X结构应用于Backbone主干网络中,另一种CSP2_X结构则应用于Neck网络中。
2.6Neck网络
FPN+PAN-YOLOv5的Neck网络仍然使用了FPN+PAN结构,但是在它的基础上做了一些改进操作,YOLOv4的Neck结构中,采用的都是普通的卷积操作。而YOLOv5的Neck网络中,采用借鉴CSPnet设计的CSP2结构,从而加强网络特征融合能力。下图展示了YOLOv4与YOLOv5的Neck网络的具体细节,通过比较我们可以发现:(1)灰色区域表示第1个不同点,YOLOv5不仅利用CSP2_\1结构代替部分CBL模块,而且去掉了下方的CBL模块;(2)绿色区域表示第2个不同点,YOLOv5不仅将Concat操作之后的CBL模块更换为CSP2_1模块,而且更换了另外一个CBL模块的位置;(3)蓝色区域表示第3个不同点,YOLOv5中将原始的CBL模块更换为CSP2_1模块。
在这里插入图片描述

2.7 输出端
(1)Bounding box损失函数
GIoU_Loss-YOLOv5中采用GIoU_Loss做Bounding box的损失函数,
(2)nms非极大值抑制
在目标检测的后处理过程中,针对很多目标框的筛选,通常需要nms操作。
因为CIOU_Loss中包含影响因子v,涉及groudtruth的信息,而测试推理时,是没有groundtruth的。
所以Yolov4在DIOU_Loss的基础上采用DIOU_nms的方式,而Yolov5中采用加权nms的方式。

第三章 实现流程
3.1pytorch 框架平台介绍
3.1.1pytorch的简介
pytorch是一个python优先的深度学习框架,是一个和tensorflow,Caffe,MXnet一样,非常底层的框架。
Torch官网:https://pytorch.org/
Torch官网的gitHub:https://github.com/torch/torch7
pypi torch : https://pypi.org/project/torch/
Pytorch是torch的python版本,是由Facebook开源的神经网络框架,专门针对 GPU 加速的深度神经网络(DNN)编程。Torch 是一个经典的对多维矩阵数据进行操作的张量(tensor )库,在机器学习和其他数学密集型应用有广泛应用。与Tensorflow的静态计算图不同,pytorch的计算图是动态的,可以根据计算需要实时改变计算图。
3.1.2 pytorch 包含的内容
3.1.2.1 overview
pytorch 由低层到上层主要有三大块功能模块,
(1) 张量计算引擎(tensor computation)
Tensor 计算引擎,类似 numpy 和 matlab,基本对象是tensor(类比 numpy 中的ndarray或matlab中的array)。除提供基于CPU的常用操作的实现外,pytorch 还提供了高效的GPU实现,这对于深度学习至关重要。
(2) 自动求导机制(autograd)
由于深度学习模型日趋复杂,因此,对自动求导的支持对于学习框架变得必不可少。pytorch 采用了动态求导机制,使用类似方法的框架包括: chainer,dynet。作为对比,theano,tensorflow 采用静态自动求导机制。
(3) 神经网络的高层库(NN)
pytorch 还提供了高层的。对于常用的网络结构,如全连接、卷积、RNN 等。同时,pytorch 还提供了常用的、optimizer 及参数。
3.1.2.2 自定义 Module
(1) Function
Function 是 pytorch 自动求导机制的核心类。Function 是无参数或者说无状态的,它只负责接收输入,返回相应的输出;对于反向,它接收输出相应的梯度,返回输入相应的梯度。
(2) Module
类似于 Function,Module 对象也是 callable ,输入和输出也是 Variable。不同的是,Module 是[可以]有参数的。Module 包含两个主要部分:参数及计算逻辑(Function 调用)。由于ReLU激活函数没有参数,这里我们以最基本的全连接层为例来说明如何自定义Module。
3.1.3pytorch的三大优势
(1)、Python优先支持策略:Pytorch主推的特性之一,就是支持python(官方的提法:puts Python first)。因为直接构建自 Python C API,Pytorch从细粒度上直接支持python的访问。相比于原生Python实现,引入的新概念很少,这不仅降低了 python 用户理解的门槛,也能保证代码基本跟原生的 python 实现一致。事实上,开发者可以直接用原生 python 代码扩展 Pytorch 的 operation。
(2)、动态图的良好支持:Tensorflow运行必须提前建好静态计算图,然后通过feed和run重复执行建好的图。但是Pytorch却不需要这么麻烦:PyTorch的程序可以在执行时动态构建/调整计算图。相对来说,pytorch具有更好的灵活性。这得益于Pytorch直接基于 python C API 构建的 python 接口。
(3)、易于Debug:Pytorch在运行时可以生成动态图,开发者就可以在堆栈跟踪中看到哪一行代码导致了错误。你甚至可以在调试器中停掉解释器并看看某个层会产生什么。
(4)、通常使用PyTorch可以使用GPU的功能代替numpy。 一个深刻的学习研究平台,提供最大的灵活性和速度。
3.2 模型、数据库准备及复现
3.2.1 下载Yolov5
下载完成之后,并且根据版本说明安装相对应的库,运行detect.py,进行检测能不能运行。
在这里插入图片描述
在这里插入图片描述

成功运行之后,能在runs/detect/exp2文件中找到被处理过的标签,如上图,说明运行成功。
3.2.2 下载数据库
https://pan.baidu.com/s/1YmZOPzcVaA0TuupMDW93SQ 
收集图片,下载labelimg对图片进行打标签操作。数据集一共106张王者荣耀游戏图片,该数据集是一名博主已经打过标签的数据集,可以直接下载来训练运用。
在这里插入图片描述

3.2.3复现
3.2.3.1 数据集配置文件
在data目录下创建一个mydata,yaml文件
在这里插入图片描述

3.2.3.2 模型配置文件
在models下建立一个mask_yolov5s.yaml
在这里插入图片描述

3.2.3.3 训练模型
在Terminal 下运行命令行代码
python train.py --data mydata.yaml --cfg yolov5s.yaml --weights yolov5s.pt --epoch 100 --batch-size 4
即可得到权重文件和一些图片信息

在这里插入图片描述

3.2.3.4 目标检测
之后运用训练好的最好的模型,来实现视频的目标检测。
在这里插入图片描述

3.3 操作流程图:
在这里插入图片描述

3.4 项目结果

最终结果保存在runs\detect\exp2
视频目标检测截图如下:
在这里插入图片描述
在这里插入图片描述

第四章 代码
detect.py中部分函数代码
@torch.no_grad()
def run(weights=‘yolov5s.pt’, # model.pt path(s)
source=‘data/images’, # file/dir/URL/glob, 0 for webcam
imgsz=640, # inference size (pixels)
conf_thres=0.25, # confidence threshold
iou_thres=0.45, # NMS IOU threshold
max_det=1000, # maximum detections per image
device=‘’, # cuda device, i.e. 0 or 0,1,2,3 or cpu
view_img=False, # show results
save_txt=False, # save results to *.txt
save_conf=False, # save confidences in --save-txt labels
save_crop=False, # save cropped prediction boxes
nosave=False, # do not save images/videos
classes=None, # filter by class: --class 0, or --class 0 2 3
agnostic_nms=False, # class-agnostic NMS
augment=False, # augmented inference
visualize=False, # visualize features
update=False, # update all models
project=‘runs/detect’, # save results to project/name
name=‘exp’, # save results to project/name
exist_ok=False, # existing project/name ok, do not increment
line_thickness=3, # bounding box thickness (pixels)
hide_labels=False, # hide labels
hide_conf=False, # hide confidences
half=False, # use FP16 half-precision inference
):
save_img = not nosave and not source.endswith(‘.txt’) # save inference images
webcam = source.isnumeric() or source.endswith(‘.txt’) or source.lower().startswith(
(‘rtsp://’, ‘rtmp://’, ‘http://’, ‘https://’))

# Directories
save_dir = increment_path(Path(project) / name, exist_ok=exist_ok)  # increment run
(save_dir / 'labels' if save_txt else save_dir).mkdir(parents=True, exist_ok=True)  # make dir

# Initialize
set_logging()
device = select_device(device)
half &= device.type != 'cpu'  # half precision only supported on CUDA

# Load model
model = attempt_load(weights, map_location=device)  # load FP32 model
stride = int(model.stride.max())  # model stride
imgsz = check_img_size(imgsz, s=stride)  # check image size
names = model.module.names if hasattr(model, 'module') else model.names  # get class names
if half:
    model.half()  # to FP16

# Second-stage classifier
classify = False
if classify:
    modelc = load_classifier(name='resnet50', n=2)  # initialize
    modelc.load_state_dict(torch.load('resnet50.pt', map_location=device)['model']).to(device).eval()

# Dataloader
if webcam:
    view_img = check_imshow()
    cudnn.benchmark = True  # set True to speed up constant image size inference
    dataset = LoadStreams(source, img_size=imgsz, stride=stride)
    bs = len(dataset)  # batch_size
else:
    dataset = LoadImages(source, img_size=imgsz, stride=stride)
    bs = 1  # batch_size
vid_path, vid_writer = [None] * bs, [None] * bs

# Run inference
if device.type != 'cpu':
    model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters())))  # run once
t0 = time.time()
for path, img, im0s, vid_cap in dataset:
    img = torch.from_numpy(img).to(device)
    img = img.half() if half else img.float()  # uint8 to fp16/32
    img /= 255.0  # 0 - 255 to 0.0 - 1.0
    if img.ndimension() == 3:
        img = img.unsqueeze(0)

    # Inference
    t1 = time_synchronized()
    pred = model(img,
                 augment=augment,
                 visualize=increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False)[0]

    # Apply NMS
    pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
    t2 = time_synchronized()

    # Apply Classifier
    if classify:
        pred = apply_classifier(pred, modelc, img, im0s)

    # Process detections
    for i, det in enumerate(pred):  # detections per image
        if webcam:  # batch_size >= 1
            p, s, im0, frame = path[i], f'{i}: ', im0s[i].copy(), dataset.count
        else:
            p, s, im0, frame = path, '', im0s.copy(), getattr(dataset, 'frame', 0)

        p = Path(p)  # to Path
        save_path = str(save_dir / p.name)  # img.jpg
        txt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}')  # img.txt
        s += '%gx%g ' % img.shape[2:]  # print string
        gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
        imc = im0.copy() if save_crop else im0  # for save_crop
        if len(det):
            # Rescale boxes from img_size to im0 size
            det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()

            # Print results
            for c in det[:, -1].unique():
                n = (det[:, -1] == c).sum()  # detections per class
                s += f"{n} {names[int(c)]}{'s' * (n > 1)}, "  # add to string

            # Write results
            for *xyxy, conf, cls in reversed(det):
                if save_txt:  # Write to file
                    xywh = (xyxy2xywh(torch.tensor(xyxy).view(1, 4)) / gn).view(-1).tolist()  # normalized xywh
                    line = (cls, *xywh, conf) if save_conf else (cls, *xywh)  # label format
                    with open(txt_path + '.txt', 'a') as f:
                        f.write(('%g ' * len(line)).rstrip() % line + '\n')

                if save_img or save_crop or view_img:  # Add bbox to image
                    c = int(cls)  # integer class
                    label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
                    plot_one_box(xyxy, im0, label=label, color=colors(c, True), line_thickness=line_thickness)
                    if save_crop:
                        save_one_box(xyxy, imc, file=save_dir / 'crops' / names[c] / f'{p.stem}.jpg', BGR=True)

        # Print time (inference + NMS)
        print(f'{s}Done. ({t2 - t1:.3f}s)')
        # Stream results
        if view_img:
            cv2.imshow(str(p), im0)
            cv2.waitKey(1)  # 1 millisecond
        # Save results (image with detections)
        if save_img:
            if dataset.mode == 'image':
                cv2.imwrite(save_path, im0)
            else:  # 'video' or 'stream'
                if vid_path[i] != save_path:  # new video
                    vid_path[i] = save_path
                    if isinstance(vid_writer[i], cv2.VideoWriter):
                        vid_writer[i].release()  # release previous video writer
                    if vid_cap:  # video
                        fps = vid_cap.get(cv2.CAP_PROP_FPS)
                        w = int(vid_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                        h = int(vid_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                    else:  # stream
                        fps, w, h = 30, im0.shape[1], im0.shape[0]
                        save_path += '.mp4'
                    vid_writer[i] = cv2.VideoWriter(save_path, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
                vid_writer[i].write(im0)

if save_txt or save_img:
    s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
    print(f"Results saved to {save_dir}{s}")

if update:
    strip_optimizer(weights)  # update model (to fix SourceChangeWarning)

print(f'Done. ({time.time() - t0:.3f}s)')

def parse_opt():
parser = argparse.ArgumentParser()
#修改权重路径
parser.add_argument(‘–weights’, nargs=‘+’, type=str, default=‘runs/train/exp/weights/best.pt’, help=‘model.pt path(s)’)
#修改测试图片路径
parser.add_argument(‘–source’, type=str, default=‘my_dates/images/test’, help=‘file/dir/URL/glob, 0 for webcam’)
parser.add_argument(‘–imgsz’, ‘–img’, ‘–img-size’, type=int, default=640, help=‘inference size (pixels)’)
parser.add_argument(‘–conf-thres’, type=float, default=0.25, help=‘confidence threshold’)
parser.add_argument(‘–iou-thres’, type=float, default=0.45, help=‘NMS IoU threshold’)
parser.add_argument(‘–max-det’, type=int, default=1000, help=‘maximum detections per image’)
parser.add_argument(‘–device’, default=‘’, help=‘cuda device, i.e. 0 or 0,1,2,3 or cpu’)
parser.add_argument(‘–view-img’, action=‘store_true’, help=‘show results’)
parser.add_argument(‘–save-txt’, action=‘store_true’, help=‘save results to *.txt’)
parser.add_argument(‘–save-conf’, action=‘store_true’, help=‘save confidences in --save-txt labels’)
parser.add_argument(‘–save-crop’, action=‘store_true’, help=‘save cropped prediction boxes’)
parser.add_argument(‘–nosave’, action=‘store_true’, help=‘do not save images/videos’)
parser.add_argument(‘–classes’, nargs=‘+’, type=int, help=‘filter by class: --class 0, or --class 0 2 3’)
parser.add_argument(‘–agnostic-nms’, action=‘store_true’, help=‘class-agnostic NMS’)
parser.add_argument(‘–augment’, action=‘store_true’, help=‘augmented inference’)
parser.add_argument(‘–visualize’, action=‘store_true’, help=‘visualize features’)
parser.add_argument(‘–update’, action=‘store_true’, help=‘update all models’)
parser.add_argument(‘–project’, default=‘runs/detect’, help=‘save results to project/name’)
parser.add_argument(‘–name’, default=‘exp’, help=‘save results to project/name’)
parser.add_argument(‘–exist-ok’, action=‘store_true’, help=‘existing project/name ok, do not increment’)
parser.add_argument(‘–line-thickness’, default=3, type=int, help=‘bounding box thickness (pixels)’)
parser.add_argument(‘–hide-labels’, default=False, action=‘store_true’, help=‘hide labels’)
parser.add_argument(‘–hide-conf’, default=False, action=‘store_true’, help=‘hide confidences’)
parser.add_argument(‘–half’, action=‘store_true’, help=‘use FP16 half-precision inference’)
opt = parser.parse_args()
return opt

def main(opt):
print(colorstr('detect: ') + ‘, ‘.join(f’{k}={v}’ for k, v in vars(opt).items()))
check_requirements(exclude=(‘tensorboard’, ‘thop’))
run(**vars(opt))

if name == “main”:
opt = parse_opt()
main(opt)

mydata.yaml 数据库配置文件
train: my_dates/images/train # 训练集位置
val: my_dates/images/train # 验证集位置
test: # test images (optional)

Classes

nc: 10 # number of classes
names: [ ‘Hero’,
‘Tower’,
‘Soldiers’,
‘Monster’,
‘Red_buff’,
‘Monster_bird’,
‘Spirit’,
‘Monster_lizard’,
‘Blue_buff’,
‘Monster_wolf’] # class names

模型配置文件

Parameters

nc: 10 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors:

  • [10,13, 16,30, 33,23] # P3/8
  • [30,61, 62,45, 59,119] # P4/16
  • [116,90, 156,198, 373,326] # P5/32

YOLOv5 backbone

backbone:

[from, number, module, args]

[[-1, 1, Focus, [64, 3]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 3, C3, [1024, False]], # 9
]

YOLOv5 head

head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, ‘nearest’]],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13

[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, ‘nearest’]],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)

[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)

[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)

[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]

第五章 学习心得
在本次的课设中,我学到了好多东西,了解了深度学习中的YOLO算法的基本内容,了解了YOLO算法从yolov1到现在的yolov5的发展历程,以及算法一步一步的改进历程。跟着教学视频做了实验,一步一步下来,确实也出错了很多,在修改的错误过程中,自己确实学到了不少的知识,也知道了自己有很多的知识欠缺,要继续努力。

参考文献:
[1]张锦,屈佩琪,孙程,罗蒙.基于改进YOLOv5的安全帽佩戴检测方法[J/OL].计算机应用:1-11[2021-12-28].http://kns.cnki.net/kcms/detail/51.1307.TP.20210908.1727.002.html.
[2]陈影.基于YOLOv5算法的道路场景目标检测应用研究[J].现代计算机,2021,27(26):55-61.
[3]Yolov5下载:https://github.com/ultralytics/yolov5
[4]视频教程:
https://www.bilibili.com/video/BV1YL4y1J7xz?p=4&share_source=copy_web
https://www.jiangdabai.com/vcat/《30天入门深度学习》系列课程-大白智能 (jiangdabai.com)
[5]数据下载:
https://pan.baidu.com/s/1YmZOPzcVaA0TuupMDW93SQ 
[6]CSDN文章:手把手教你使用YOLOV5训练自己的目标检测模型-口罩检测
[7]CSDN文章:YOLOv5(PyTorch)目标检测:原理与源码解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值