YOLOv5:解读general.py

news2024/11/26 0:51:48

YOLOv5:解读general.py

前言

  • 记录一下自己阅读general.py代码的一些重要点,方便自己查阅。特别感谢,在参考里,列举的博文链接,写得很好,对本人阅读理解yolo.py代码,有很大帮助。
  • 由于本人水平有限,难免出现错漏,敬请批评改正。
  • 更多精彩内容,可点击进入YOLO系列专栏、自然语言处理
    专栏或我的个人主页查看
  • 基于DETR的人脸伪装检测
  • YOLOv7训练自己的数据集(口罩检测)
  • YOLOv8训练自己的数据集(足球检测)
  • YOLOv5:TensorRT加速YOLOv5模型推理
  • YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU
  • 玩转Jetson Nano(五):TensorRT加速YOLOv5目标检测
  • YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力机制
  • YOLOv5:yolov5s.yaml配置文件解读、增加小目标检测层
  • Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集
  • YOLOv5:使用7.0版本训练自己的实例分割模型(车辆、行人、路标、车道线等实例分割)
  • 使用Kaggle GPU资源免费体验Stable Diffusion开源项目

前提条件

  • 熟悉Python

相关介绍

  • Python是一种跨平台的计算机程序设计语言。是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。
  • PyTorch 是一个深度学习框架,封装好了很多网络和深度学习相关的工具方便我们调用,而不用我们一个个去单独写了。它分为 CPU 和 GPU 版本,其他框架还有 TensorFlow、Caffe 等。PyTorch 是由 Facebook 人工智能研究院(FAIR)基于 Torch 推出的,它是一个基于 Python 的可续计算包,提供两个高级功能:1、具有强大的 GPU 加速的张量计算(如 NumPy);2、构建深度神经网络时的自动微分机制。
  • YOLOv5是一种单阶段目标检测算法,该算法在YOLOv4的基础上添加了一些新的改进思路,使其速度与精度都得到了极大的性能提升。它是一个在COCO数据集上预训练的物体检测架构和模型系列,代表了Ultralytics对未来视觉AI方法的开源研究,其中包含了经过数千小时的研究和开发而形成的经验教训和最佳实践。

general.py

clip_boxes

  • 在 Python 中,torch.clamp_() 和numpy.clip()是一个用于限制数值范围的方法,该方法接受三个参数:最小值、最大值和需要被限制的数值。
  • 方法的作用是将给定的数值限制在最小值和最大值之间,返回一个新的值。如果原始数值小于最小值,则返回最小值;如果原始数值大于最大值,则返回最大值;如果原始数值在最小值和最大值之间,则返回原始数值。

在这里插入图片描述

def clip_boxes(boxes, shape):
    # Clip boxes (xyxy) to image shape (height, width)
    if isinstance(boxes, torch.Tensor):  # faster individually
        boxes[..., 0].clamp_(0, shape[1])  # x1
        boxes[..., 1].clamp_(0, shape[0])  # y1
        boxes[..., 2].clamp_(0, shape[1])  # x2
        boxes[..., 3].clamp_(0, shape[0])  # y2
    else:  # np.array (faster grouped)
        boxes[..., [0, 2]] = boxes[..., [0, 2]].clip(0, shape[1])  # x1, x2
        boxes[..., [1, 3]] = boxes[..., [1, 3]].clip(0, shape[0])  # y1, y2

scale_boxes ★ \bigstar

在这里插入图片描述

def scale_boxes(img1_shape, boxes, img0_shape, ratio_pad=None):
    # Rescale boxes (xyxy) from img1_shape to img0_shape
    if ratio_pad is None:  # calculate from img0_shape
        gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])  # gain  = old / new
        pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2  # wh padding
    else:
        gain = ratio_pad[0][0]
        pad = ratio_pad[1]

    boxes[..., [0, 2]] -= pad[0]  # x padding
    boxes[..., [1, 3]] -= pad[1]  # y padding
    boxes[..., :4] /= gain
    clip_boxes(boxes, img0_shape)
    return boxes

xywh2xyxy

在这里插入图片描述

def xywh2xyxy(x):
    # Convert nx4 boxes from [x, y, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right
    y = x.clone() if isinstance(x, torch.Tensor) else np.copy(x)
    y[..., 0] = x[..., 0] - x[..., 2] / 2  # top left x
    y[..., 1] = x[..., 1] - x[..., 3] / 2  # top left y
    y[..., 2] = x[..., 0] + x[..., 2] / 2  # bottom right x
    y[..., 3] = x[..., 1] + x[..., 3] / 2  # bottom right y
    return y

non_max_suppression ★ ★ ★ \bigstar\bigstar\bigstar ★★★

  • torchvision.ops.nms 是 PyTorch 的 torchvision 库中提供的一个函数,用于实现非极大值抑制(Non-Maximum Suppression,NMS)操作。这个函数对输入的候选框(bounding boxes)进行排序,并根据给定的 IoU 阈值去除重叠度较高的框。
  • 函数的输入参数如下:
    • boxes:一个包含候选框的张量,每个框由一个或多个边界框坐标组成。每个边界框由四个元素表示,分别是左上角和右下角的坐标(x1, y1, x2, y2)。
    • scores:一个与 boxes 相同形状的张量,表示每个框的置信度分数。
    • iou_thres:一个阈值,用于控制哪些框被认为是重叠的。
  • 函数的输出是一个张量,其中包含经过非极大值抑制处理后的结果。
  • 传统的NMS算法,具体流程如下:
    • 步骤一:将所有矩形框按照不同的类别标签分组,组内按照置信度高低得分进行排序;
    • 步骤二:将步骤一中得分最高的矩形框拿出来,遍历剩余矩形框,计算与当前得分最高的矩形框的交并比,将剩余矩形框中大于设定的IOU阈值的框删除;
    • 步骤三:将步骤二结果中,对剩余的矩形框重复步骤二操作,直到处理完所有矩形框;
  • 在YOLOv5中,non_max_suppression函数,具体流程如下:
    在这里插入图片描述
def non_max_suppression(
        prediction, 
        conf_thres=0.25,
        iou_thres=0.45,
        classes=None,
        agnostic=False,
        multi_label=False,
        labels=(),
        max_det=300,
        nm=0,  # number of masks
):
    """Non-Maximum Suppression (NMS) on inference results to reject overlapping detections
    Arguments:
            prediction : 1个 ,[bs, anchor_num*grid_w*grid_h, xywh+c+5classes] = [4,3*260*260+3*130*130+3*65*65*65,10] = [4, 266175, 10]
    
    Returns:
         list of detections, on (n,6) tensor per image [xyxy, conf, cls]
    """

    # Checks
    assert 0 <= conf_thres <= 1, f'Invalid Confidence threshold {conf_thres}, valid values are between 0.0 and 1.0'
    assert 0 <= iou_thres <= 1, f'Invalid IoU {iou_thres}, valid values are between 0.0 and 1.0'
    if isinstance(prediction, (list, tuple)):  # YOLOv5 model in validation model, output = (inference_out, loss_out)
        prediction = prediction[0]  # select only inference output

    device = prediction.device # 设置推理设备
    mps = 'mps' in device.type  # Apple MPS
    if mps:  # MPS not fully supported yet, convert tensors to CPU before NMS
        prediction = prediction.cpu()
    bs = prediction.shape[0]  # batch size
    nc = prediction.shape[2] - nm - 5  # number of classes # 这里的5表示[x,y,w,h,conf]这5个数值
    xc = prediction[..., 4] > conf_thres  # candidates # 预测框置信度> conf_thres阈值,选为候选框,xc = [True,False,....]

    # Settings
    # min_wh = 2  # (pixels) minimum box width and height # 预测物体宽度和高度的大小范围 [min_wh, max_wh]
    max_wh = 7680  # (pixels) maximum box width and height # 
    max_nms = 30000  # maximum number of boxes into torchvision.ops.nms()
    time_limit = 0.5 + 0.05 * bs  # seconds to quit after # 每个图像最多检测物体的个数 
    redundant = True  # require redundant detections # 是否需要冗余的detections
    multi_label &= nc > 1  # multiple labels per box (adds 0.5ms/img)
    merge = False  # use merge-NMS

    t = time.time()
    mi = 5 + nc  # mask start index
    # batch_size个output  存放最终筛选后的预测框结果
    output = [torch.zeros((0, 6 + nm), device=prediction.device)] * bs
    # 遍历预测框结果
    for xi, x in enumerate(prediction):  # image index, image inference
        # Apply constraints # 第一次过滤 虑除超小anchor标和超大anchor 
        # x[((x[..., 2:4] < min_wh) | (x[..., 2:4] > max_wh)).any(1), 4] = 0  # width-height

        # # 第二次过滤 根据conf_thres虑除背景目标(obj_conf<conf_thres 0.1的目标 置信度极低的目标) 
        x = x[xc[xi]]  # confidence 

        # Cat apriori labels if autolabelling
        if labels and len(labels[xi]):
            lb = labels[xi]
            v = torch.zeros((len(lb), nc + nm + 5), device=x.device)
            v[:, :4] = lb[:, 1:5]  # box
            v[:, 4] = 1.0  # conf
            v[range(len(lb)), lb[:, 0].long() + 5] = 1.0  # cls
            x = torch.cat((x, v), 0)

        # If none remain process next image
        ## 经过前两次过滤后如果该feature map没有目标框了,就结束这轮直接进行下一张图
        if not x.shape[0]:
            continue

        # Compute conf
        x[:, 5:] *= x[:, 4:5]  # conf = obj_conf * cls_conf

        # Box/Mask # (center x, center y, width, height) to (x1, y1, x2, y2) 左上角 右下角
        box = xywh2xyxy(x[:, :4])  # center_x, center_y, width, height) to (x1, y1, x2, y2)
        mask = x[:, mi:]  # zero columns if no masks

        # Detections matrix nx6 (xyxy, conf, cls)
        if multi_label:
            # 第三次过滤:针对每个类别score(obj_conf * cls_conf) > conf_thres   
            # 这里一个框是有可能有多个物体的,所以要筛选
            # nonzero: 获得矩阵中的非0(True)数据的下标  a.t(): 将a矩阵拆开
            # i: box下标    j: 类别index   过滤了两个score太低的
            i, j = (x[:, 5:mi] > conf_thres).nonzero(as_tuple=False).T
            # pred = [43, xyxy+score+class] [43, 6]
            # unsqueeze(1): [43] => [43, 1] add batch dimension
            # box[i]: [43,4] xyxy
            # pred[i, j + 5].unsqueeze(1): [43,1] score  对每个i,取第(j+5)个位置的值(第j个class的值cla_conf)
            # j.float().unsqueeze(1): [43,1] class
            x = torch.cat((box[i], x[i, 5 + j, None], j[:, None].float(), mask[i]), 1)
        else:  # best class only
            conf, j = x[:, 5:mi].max(1, keepdim=True) # 一个类别直接取分数最大类的即可
            x = torch.cat((box, conf, j.float(), mask), 1)[conf.view(-1) > conf_thres]

        # Filter by class 是否只保留特定的类别  默认None  不执行这里
        if classes is not None:
            x = x[(x[:, 5:6] == torch.tensor(classes, device=x.device)).any(1)]

        # Apply finite constraint
        # 检测数据是否为有限数 Apply finite constraint  第四次过滤,这次可有可无,一般没什么用 所以这里给他注释了
        # if not torch.isfinite(x).all():
        #     x = x[torch.isfinite(x).all(1)]

        # Check shape
        n = x.shape[0]  # number of boxes
        if not n:  # no boxes # 如果经过第三次过滤该feature map没有目标框了,就结束这次直接进行下一张图
            continue
        # 如果经过第三次过滤该feature map还要很多框(>max_nms)   就需要排序
        x = x[x[:, 4].argsort(descending=True)[:max_nms]]  # sort by confidence and remove excess boxes

        # Batched NMS # 第五次过滤 Batched NMS  
        c = x[:, 5:6] * (0 if agnostic else max_wh)  # classes
        # 做个切片 得到boxes和scores   不同类别的box位置信息加上一个很大的数但又不同的数c
        # 这样作非极大抑制的时候不同类别的框就不会掺和到一块了  这是一个作nms挺巧妙的技巧
        boxes, scores = x[:, :4] + c, x[:, 4]  # boxes (offset by class), scores
        # 返回nms过滤后的bounding box(boxes)的索引(降序排列)
        # i=tensor([18, 19, 32, 25, 27])   nms后只剩下比较少的预测框了
        i = torchvision.ops.nms(boxes, scores, iou_thres)  # NMS

        i = i[:max_det]  # limit detections # 限制NMS后的最大框数

        if merge and (1 < n < 3E3):  # Merge NMS (boxes merged using weighted mean)
            # update boxes as boxes(i,4) = weights(i,n) * boxes(n,4)
            iou = box_iou(boxes[i], boxes) > iou_thres  # iou matrix
            weights = iou * scores[None]  # box weights 正比于 iou * scores
            # bounding box合并  其实就是把权重和框相乘再除以权重之和
            x[i, :4] = torch.mm(weights, x[:, :4]).float() / weights.sum(1, keepdim=True)  # merged boxes
            if redundant:
                i = i[iou.sum(1) > 1]  # require redundancy

        output[xi] = x[i]
        if mps:
            output[xi] = output[xi].to(device)
        # 看下时间超没超时  超时没做完的就不做了
        if (time.time() - t) > time_limit:
            LOGGER.warning(f'WARNING ⚠️ NMS time limit {time_limit:.3f}s exceeded')
            break  # time limit exceeded

    return output

未完待续

在general.py中,不止上面提到的类和函数,但上面提及的类和函数是general.py中最关键的部分。其余函数,有兴趣者,可自行查阅。如果有空,我也会继续补充。

参考

[1] https://github.com/ultralytics/yolov5
[2] 【YOLOV5-5.x 源码解读】datasets.py_满船清梦压星河HK的博客-CSDN博客
[3] https://blog.csdn.net/weixin_51322383/article/details/130447757
[4] https://blog.csdn.net/qq_38253797/article/details/117920079

  • 记录一下自己阅读general.py代码的一些重要点,方便自己查阅。特别感谢,在参考里,列举的博文链接,写得很好,对本人阅读理解yolo.py代码,有很大帮助。
  • 由于本人水平有限,难免出现错漏,敬请批评改正。
  • 更多精彩内容,可点击进入YOLO系列专栏、自然语言处理
    专栏或我的个人主页查看
  • 基于DETR的人脸伪装检测
  • YOLOv7训练自己的数据集(口罩检测)
  • YOLOv8训练自己的数据集(足球检测)
  • YOLOv5:TensorRT加速YOLOv5模型推理
  • YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU
  • 玩转Jetson Nano(五):TensorRT加速YOLOv5目标检测
  • YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力机制
  • YOLOv5:yolov5s.yaml配置文件解读、增加小目标检测层
  • Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集
  • YOLOv5:使用7.0版本训练自己的实例分割模型(车辆、行人、路标、车道线等实例分割)
  • 使用Kaggle GPU资源免费体验Stable Diffusion开源项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/953181.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java基础笔试题(一)

系列文章目录 Java基础知识题(一) Java基础知识题(二) Java基础知识题(三) Java基础知识题(四) Java基础知识题(五) 文章目录 系列文章目录 模块1 单选题1 单选题2 单选题2 单选题4 单选题5 模块2 单选题1 单选题2 补充一&#xff1a;理解is-a&#xff0c;has…

【python爬虫】5.爬虫实操(歌词爬取)

文章目录 前言项目&#xff1a;寻找周杰伦分析过程代码实现重新分析过程什么是NetworkNetwork怎么用什么是XHR&#xff1f;XHR怎么请求&#xff1f;json是什么&#xff1f;json数据如何解析&#xff1f;实操&#xff1a;完成代码实现 一个总结一个复习 前言 这关让我们一起来寻…

GraphQL渗透测试案例及防御办法

什么是GraphQL GraphQL 是一种 API 查询语言&#xff0c;旨在促进客户端和服务器之间的高效通信。它使用户能够准确指定他们在响应中所需的数据&#xff0c;从而有助于避免有时使用 REST API 看到的大型响应对象和多个调用。 GraphQL 服务定义了一个合约&#xff0c;客户端可…

【Linux系列】使用虚拟机安装Linux系统

首发博客地址 首发博客地址[1] 系列文章地址[2] 下载虚拟机 请从官网下载&#xff1a; https://customerconnect.vmware.com/en/downloads/info/slug/desktop_end_user_computing/vmware_workstation_player/17_0 如需不限速下载&#xff0c;请关注【程序员朱永胜】并回复 1018…

自研的外贸搜索工具

全球智能搜索 独有的VVPN技术有效绕过各种限制获取国外搜索引擎数据 1.支持全球所有国家搜索引擎&#xff0c;及社交平台&#xff0c;精准定位优质的外贸客户. 2.全球任意国家地区实时采集. 3.搜索引擎全网邮箱电话采集 4.社交平台一键查看采集&#xff08;Facebook,Twitter,L…

基于Matlab实现频谱分析(附上源码+数据集)

Matlab是一个功能强大的数值计算和科学计算软件&#xff0c;可以用于频谱分析。频谱分析是一种信号处理技术&#xff0c;用于将时域信号转换为频域信号&#xff0c;以便更好地理解信号的频率特性。本文将介绍使用Matlab实现频谱分析的方法。 文章目录 部分源码完整源码数据集下…

Samba服务器

目录 一、什么是Samba&#xff1f; 二、Samba进程 三、Samba主要功能 四、Samba工作流程 五、Samba安全级别 六、Sam主配置文件/etc/samba/smb.conf 七、Samba服务配置案例 一、什么是Samba&#xff1f; Samba可以让linux计算机和windows计算机之间实现文件和打印机资源共享的一…

JavaWeb 速通Ajax

目录 一、Ajax快速入门 1.基本介绍 : 2.使用原理 : 二、Ajax经典入门案例 1.需求 : 2.前端页面实现 : 3. 处理HTTP请求的servlet实现 4.引入jar包及druid配置文件、工具类 : 5.Domain层实现 : 6.DAO层实现 : 7.Service层实现 : 8.运行测试 : 三、JQuery操作Ajax 1 …

Java:Stream流的使用步骤,中间方法,终结方法,收集Stream流

Stream流的相关知识 Stream流的使用步骤 1.获取Stream流 Stream流常见的中间方法 如果两个Stream流类型不一样&#xff0c;那么合并的时候就要变成Object类型 Stream流的常见的终结方法 转到数组中去

Angular安全专辑之四 —— 避免服务端可能的资源耗尽(NodeJS)

express-rate-limit是一个简单实用的npm包,用于在Express应用程序中实现速率限制。它可以帮助防止DDoS攻击和暴力破解,同时还允许对API端点进行流控。 express-rate-limit及其主要功能 express-rate-limit是Express框架的一个流行中间件,它允许根据IP地址或其他标准轻松地对请求…

中国智慧燃气行业市场需求

文章来源&#xff1a;中研普华产业研究院 关键词&#xff1a;智慧燃气、智慧燃气场站、智慧燃气平台、设备设施数字化、数字孪生、工业互联网 智慧燃气&#xff0c;是以城市输气管网为基础&#xff0c;各终端用户协调发展&#xff0c;以信息通信平台为支撑&#xff0c;具有信…

java spring cloud 企业工程管理系统源码+二次开发+定制化服务

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

解决 .csv 文件上传到 pgsql 的字符报错问题

目录 背景问题解决办法 背景 上传 .csv 文件进行数据导入到 pg 时&#xff0c;报错显示如下&#xff1a; ods.tbl_inp_fee_detail.csv数据上传失败 报错信息:org.postgresql.util.PSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00 Where: C…

NPDP认证|加班越多,产品经理的能力提升越快吗?

产品经理是现代企业中非常重要的职位&#xff0c;他们负责规划、设计、开发和推广公司的产品。为了使产品能够更好地满足市场需求&#xff0c;产品经理需要不断地提升自己的能力&#xff0c;以应对日益变化的竞争环境。有时&#xff0c;人们会认为加班是提高产品经理能力的途径…

链式栈StackT

C关键词&#xff1a;内部类/模板类/头插 C自学精简教程 目录(必读) C数据结构与算法实现&#xff08;目录&#xff09; 栈的内存结构 空栈&#xff1a; 有一个元素的栈&#xff1a; 多个元素的栈&#xff1a; 成员函数说明 0 clear 清空栈 clear 函数负责将栈的对内存释放…

[js逆向补环境专栏]过xhs的x2 x-s环境检测 -- part1

[补环境]过xhs的x2环境检测 – part1 Xhs的jsvmp用算法逆向确实容易头秃&#xff0c;扣代码对vmp而言也用处不大&#xff0c;此时补环境的重要性就出来了&#xff0c;通过把运行js的环境伪造得像浏览器一样&#xff0c;就能模拟出好像请求都是通过浏览器发起的一样。 这里要区…

光模块温度报警的原因及解决措施

光模块是数据中心网络中的关键组件&#xff0c;它们在高温环境下可能会受到影响。如果光模块的温度超过正常范围&#xff0c;可能会导致网络故障和光模块损坏。因此&#xff0c;了解光模块的温度报警并采取相应的解决措施非常重要。 一、光模块温度报警的原因 光模块温度报警通…

Linux之虚拟主机功能

目录 虚拟主机功能 概述 基于 IP 地址的虚拟主机 原理 案例 --- 增加多个IP地址&#xff0c;实现基于不同IP地址的虚拟主机功能 基于端口号的虚拟主机 原理 案例 --- 基于不同端口号的虚拟主机 基于域名的虚拟主机 原理 域名解析 案例 --- 使用2个域名建立虚拟主机网…

2023年6月GESP C++ 二级试卷解析

2023年6月GESP C 二级试卷解析 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 1.高级语言编写的程序需要经过以下&#xff08; &#xff09;操作&#xff0c;可以生成在计算机上运行的可执行代码。 A.编辑 B.保存 C.调试 D.编译 【答案】D 【考纲知识点…

问ChatGPT如何优雅地分手/离婚,然后由心理学专家验证它说对了什么

ChatGPT是一种由AI驱动的写作生成器&#xff0c;它利用互联网上的各种信息回复人类问题与要求。它可以回答问题、讲笑话、创意写作和整理研究。 ChatGPT可以取代艺术家吗&#xff1f;ChatGPT可以创作交响曲吗&#xff1f;ChatGPT的内容是否都合乎伦理&#xff1f;面对AI的完全…