ultralytics-YOLOv11的目标检测解析

1. Python的调用

from ultralytics import YOLO
import os
def detect_predict():model = YOLO('../weights/yolo11n.pt')print(model)results = model('../ultralytics/assets/bus.jpg')if not os.path.exists(results[0].save_dir):os.makedirs(results[0].save_dir)for result in results:filename = result.path.split("\\")[-1]filedir = result.save_dir + "\\" + filenameresult.save(filedir)

运行结果:

模型训练,基于coco8数据:

from ultralytics import YOLO
def detect_train():model = YOLO("yolo11l.pt")  # Load a modeltrain_results = model.train(   # Train the modeldata="coco8.yaml",  # path to dataset YAMLepochs=100,  # number of training epochsimgsz=640,  # training image sizedevice="0",  # device to run on, i.e. device=0 or device=0,1,2,3 or device=cpu)metrics = model.val()  # Evaluate model performance on the validation setresults = model("../ultralytics/assets/bus.jpg")  # Perform object detection on an imageresults[0].show()# Export the model to ONNX formatpath = model.export(format="onnx")  # return path to exported model

2. 网络结构图

图2-1 yolo11-detection网络结构图

其中depth参数控制C3k2,即C3k2_X中,X*depth.

3. 损失函数

3.1 损失函数的定位

ultralytics中损失函数定位:ultralytics.engine.train()-->ultralytics.engine.trainer.train()--> ultralytics.engine.trainer._do_train(),其中以下为调用损失位置:

即模型的前向推理过程触发损失函数计算。同debug到该处,获取模型名称如下:

DetectionModel类中的函数如下:

其中DetectionModel函数继承自BaseModel,损失调用如下

经debug调用self.loss函数,其中ultralytics.utls.loss.v8DetectionLoss函数是具体损失计算位置

self.criterion(preds, batch)形式调用,即v8DetectionLoss类中的__call__函数,具体如下

3.2 损失函数具体分析

(1) 前向推理与anchor构造

前向处理分成三个尺度: ,其中B表示batch_size,

。通过debug模式三个尺度生成的list如下:

需要把三个尺度分成预测类别(80个类别)和检测框,其中 ,具体如下:

以三个尺度构造anchor,其中以每个方格中心点作为anchor_point,三个尺度总共有8400个anchor_point,如图3-1所示。通过debug获取全部anchor_points与anchor_points对应的stride_tensor,如下:

图3-1 anchor_point的构造

(2) GT目标框与预测框构建

GT目标框的构建,包括batch_idx,cls,bboxes,得到 ,其中n表示batch中的标注的目标框数量,6=1+4+1。

 self.preprocess函数的作用是输出 ,构建B个 的矩阵,其中 表示B个图像中标注框最大的数量,不足最大数量的行设置为全0,5表示cls+bbox

预测框的构建主要是函数bbox_decode,即对前向推理的pred_distri根据anchor_points对pred_distri做解码操作。解码时,pred_distri由 变为 ,具体是16个预测值做softmax后与[0,1,2,…,15]做矩阵乘法,如下 

然后pred_dist得到的是左上角、右下角距离每个anchor_point中心点的距离,通过dist2bbox转换为xyxy形式的坐标,如下所示。anchor_points为中心点的坐标,最后得到预测bboxes。 

 (3) 任务分配器

任务分配器即ultralytics.utils.tal.TaskAlignedAssigner类,主要实现以该类的forward函数。其中主要的函数为get_pos_mask、select_highest_overlaps、get_targets。

get_pos_mask:获取anchor预测真实框的mask

def get_pos_mask(self, pd_scores, pd_bboxes, gt_labels, gt_bboxes, anc_points, mask_gt):"""Get in_gts mask, (b, max_num_obj, h*w)."""mask_in_gts = self.select_candidates_in_gts(anc_points, gt_bboxes)  # mask_in_gts:4x7x8400# Get anchor_align metric, (b, max_num_obj, h*w)align_metric, overlaps = self.get_box_metrics(pd_scores, pd_bboxes, gt_labels, gt_bboxes, mask_in_gts * mask_gt)# Get topk_metric mask, (b, max_num_obj, h*w)mask_topk = self.select_topk_candidates(align_metric, topk_mask=mask_gt.expand(-1, -1, self.topk).bool())# Merge all mask to a final mask, (b, max_num_obj, h*w)mask_pos = mask_topk * mask_in_gts * mask_gtreturn mask_pos, align_metric, overlaps

select_candidates_in_gts函数的主要作用是根据真实框lr、br距离anchor_point的距离筛选anchor_points。其中筛选的条件是四个距离值大于1e-9,如图3-2所示。该函数输出如下:

其中mask_in_gts表示0或1的矩阵。

 图3-2 有效anchor_point的筛选

get_box_metrics主要是计算预测框与一个batch的GT框的CIOU,以及一个batch的GT类别位置处预测score,通过这两个计算得到align_metric。其中该函数的mask_gt的计算由select_candidates_in_gts获取的mask_in_gts与一个batch的mask_gt相乘得到,mask_in_gts: ,mask_gt: 。然后得到新的mask_gt: ,如下所示,后续的score与box框的筛选都通过新mask_gt获取。

构造batch_idx与cls_idx,如下 

根据构造的idx从pd_scores中获取mask_gt相应位置值,然后赋值给bbox_scores,mask_gt的其余部分为0,如下 

 分别扩展pd_bboxes、gt_bboxes,使其两则维度相同,然后通过新mask_gt筛选预测框与真实框,通过CIOU计算overlaps,如下

最后计算align_metric,计算公式如下

alpha=0.5,beta=6.0。

 select_topk_candidates由align_metric筛选top10候选mask_topk。其中该函数的输入topk_mask由mask_gt: 复制topk中的k=10份得到topk_mask: 。筛选align_metric中top10的值与idx,如下

 其中topk_idxs的值域为[0,8400),topk_metrics,topk_idxs,topk_mask尺寸都为 。返回mask_topk的尺寸为

 最后merge所有的mask返回为mask_pos,其中mask_topk、mask_in_gts大小为 ,mask_gt大小为 ,具体代码如下

select_highest_overlaps:当一个anchor分配多个检测框时,选择overlap最大的

def select_highest_overlaps(mask_pos, overlaps, n_max_boxes):"""Select anchor boxes with highest IoU when assigned to multiple ground truths."""# Convert (b, n_max_boxes, h*w) -> (b, h*w)fg_mask = mask_pos.sum(-2)if fg_mask.max() > 1:  # one anchor is assigned to multiple gt_bboxesmask_multi_gts = (fg_mask.unsqueeze(1) > 1).expand(-1, n_max_boxes, -1)  # (b, n_max_boxes, h*w)max_overlaps_idx = overlaps.argmax(1)  # (b, h*w)is_max_overlaps = torch.zeros(mask_pos.shape, dtype=mask_pos.dtype, device=mask_pos.device)is_max_overlaps.scatter_(1, max_overlaps_idx.unsqueeze(1), 1)mask_pos = torch.where(mask_multi_gts, is_max_overlaps, mask_pos).float()  # (b, n_max_boxes, h*w)fg_mask = mask_pos.sum(-2)# Find each grid serve which gt(index)target_gt_idx = mask_pos.argmax(-2)  # (b, h*w)return target_gt_idx, fg_mask, mask_pos

mask_pos: ,overlap: ,mask_multi_gts获取一个anchor预测多个gt框的位置,max_overlaps_idx每个anchor中overlap值最大的位置获取,通过torch.where更新mask_pos,即一个anchor分配多个框时,选择overlap最大GT,分配到该anchor上。最后返回fg_mask(anchor中分配GT框的mask)、target_gt_idx(anchor中分配GT框的idx)、

尺寸大小的mask_pos。

get_targets

def get_targets(self, gt_labels, gt_bboxes, target_gt_idx, fg_mask):# Assigned target labels, (b, 1)batch_ind = torch.arange(end=self.bs, dtype=torch.int64, device=gt_labels.device)[..., None]target_gt_idx = target_gt_idx + batch_ind * self.n_max_boxes  # (b, h*w)target_labels = gt_labels.long().flatten()[target_gt_idx]  # (b, h*w)  # 获取anchor分配GT框的类别# Assigned target boxes, (b, max_num_obj, 4) -> (b, h*w, 4)target_bboxes = gt_bboxes.view(-1, gt_bboxes.shape[-1])[target_gt_idx]  # 获取anchor分配GT框的坐标bbox# Assigned target scorestarget_labels.clamp_(0)# 10x faster than F.one_hot()target_scores = torch.zeros((target_labels.shape[0], target_labels.shape[1], self.num_classes),dtype=torch.int64,device=target_labels.device,)  # (b, h*w, 80)target_scores.scatter_(2, target_labels.unsqueeze(-1), 1)fg_scores_mask = fg_mask[:, :, None].repeat(1, 1, self.num_classes)  # (b, h*w, 80)target_scores = torch.where(fg_scores_mask > 0, target_scores, 0)  # 通过fg_scores_mask限制target_scoresreturn target_labels, target_bboxes, target_scores

 target_gt_idx是[0,n_max_boxes-1]的值,更新索引值,不同batch_idx索引唯一,如下

构造one-hot的target_scores,每个anchor都是one-hot,长度为80,如下

最后返回 的target_labels, 的target_bboxes, 大小one-hot的target_scores。

任务分配器最后步骤是做归一化处理,如下所示。

# Normalize
align_metric *= mask_pos
pos_align_metrics = align_metric.amax(dim=-1, keepdim=True)  # b, max_num_obj
pos_overlaps = (overlaps * mask_pos).amax(dim=-1, keepdim=True)  # b, max_num_obj
# align_metric/pos_align_metrics值域[0,1],尺寸为b, max_num_obj, 8400
norm_align_metric = (align_metric * pos_overlaps / (pos_align_metrics + self.eps)).amax(-2).unsqueeze(-1) #b,8400,1
target_scores = target_scores * norm_align_metric  # [b,8400,80] * [b,8400,1]

最终TaskAlignedAssigner返回五个参数,如下

 (4) 损失计算

Cls loss通过BCE计算,pred_scores与target_scores的尺寸为 ,其中BCE的计算公式如下:

Box loss计算loss_iou与loss_dfl,具体的计算如下

# Bbox loss
if fg_mask.sum():target_bboxes /= stride_tensor  # [b,8400,4] / [8400,1]loss[0], loss[2] = self.bbox_loss(  # 计算loss_iou, loss_dflpred_distri, pred_bboxes, anchor_points, target_bboxes, target_scores, target_scores_sum, fg_mask)
loss[0] *= self.hyp.box  # box gain = 7.5
loss[1] *= self.hyp.cls  # cls gain = 0.5
loss[2] *= self.hyp.dfl  # dfl gain = 1.5
return loss.sum() * batch_size, loss.detach()  # loss(box, cls, dfl)

 bbox_loss中的计算代码如下,其中包括loss_iou与loss_dfl两部分。

weight = target_scores.sum(-1)[fg_mask].unsqueeze(-1)  # 计算权重,target_scores:b,8400,80, fg_mask:b,8400
iou = bbox_iou(pred_bboxes[fg_mask], target_bboxes[fg_mask], xywh=False, CIoU=True)  # 在fg_mask下,计算真实框与预测框CIoU
loss_iou = ((1.0 - iou) * weight).sum() / target_scores_sum  # iou损失计算# DFL loss
if self.dfl_loss:target_ltrb = bbox2dist(anchor_points, target_bboxes, self.dfl_loss.reg_max - 1)  # box转换成距中心点距离
# pred_dist[fg_mask]:210x64-->840x16loss_dfl = self.dfl_loss(pred_dist[fg_mask].view(-1, self.dfl_loss.reg_max), target_ltrb[fg_mask]) * weightloss_dfl = loss_dfl.sum() / target_scores_sum  # 与iou损失一样,除以target_scores_sum
else:loss_dfl = torch.tensor(0.0).to(pred_dist.device)return loss_iou, loss_dfl

然后DFLoss如下,主要是对预测距离与真实距离做交叉熵,并加权平均计算值。其中左右权重的计算遵循距离值越大,权重就越小的原则。

target = target.clamp_(0, self.reg_max - 1 - 0.01)  # n, 4
tl = target.long()  # target left 真实框向左取整
tr = tl + 1  # target right  真实框向右取整
wl = tr - target  # weight left  向右取整-目标得到左边的权重
wr = 1 - wl  # weight right  向左取整-目标得到右边的权重
return (  # 左右预测距离与真实距离做交叉熵计算,并乘以权重F.cross_entropy(pred_dist, tl.view(-1), reduction="none").view(tl.shape) * wl+ F.cross_entropy(pred_dist, tr.view(-1), reduction="none").view(tl.shape) * wr
).mean(-1, keepdim=True)

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

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

相关文章

【AI系统】CANN 算子类型

CANN 算子类型 算子是编程和数学中的重要概念,它们是用于执行特定操作的符号或函数,以便处理输入值并生成输出值。本文将会介绍 CANN 算子类型及其在 AI 编程和神经网络中的应用,以及华为 CANN 算子在 AI CPU 的详细架构和开发要求。 算子基…

服务器与普通电脑有什么区别?

服务器和普通电脑(通常指的是个人计算机,即PC)有众多相似之处,主要构成包含:CPU,内存,芯片,I/O总线设备,电源,机箱及操作系统软件等,鉴于使用要求…

hhdb数据库介绍(10-33)

管理 数据归档 归档记录查询 功能入口:“管理->数据归档->归档记录查询” 需要确保配置的归档用户对数据归档规则所在的逻辑库具备CREATE权限,以及对原数据表具有所有权限。 清理归档数据 (一)功能入口:“…

重学设计模式-工厂模式(简单工厂模式,工厂方法模式,抽象工厂模式)

在平常的学习和工作中,我们创建对象一般会直接用new,但是很多时候直接new会存在一些问题,而且直接new会让我们的代码变得非常繁杂,这时候就会巧妙的用到设计模式,平常我们通过力扣学习的算法可能并不会在我们工作中用到…

微服务springboot详细解析(一)

目录 1.Spring概述 2.什么是SpringBoot? 3.第一个SpringBoot程序 4.配置参数优先级 5.springboot自动装配原理 6.SpringBootApplication&SpringApplication.run 7.ConfigurationProperties(prefix "") 8.Validated数据校验 29、聊聊该如何写一…

华为HarmonyOS 让应用快速拥有账号能力 -- 2 获取用户头像昵称

场景介绍 如应用需要完善用户头像昵称信息,可使用Account Kit提供的头像昵称授权能力,用户允许应用获取头像昵称后,可快速完成个人信息填写。以下只针对Account kit提供的头像昵称授权能力进行介绍,若要获取头像还可通过场景化控…

供应链系统设计-何为“前”“中”“后”台系统

概述 大家看文章或交流的时候,经常听到听到XX前台系统、XX中台系统、XX后台系统。而且经常容易混淆并且系统边界定义模糊不清,今天就和大家讨论一下什么是前台、中台和后台系统。 不知道大家对于“康威定律”是否熟悉。在这里简单的给大家介绍一下&…

vue中使用socket.io统计在线用户

目录 一、引入相关模块 二、store/modules 中封装socketio 三、后端代码(nodejs) 一、引入相关模块 main.js 中参考以下代码 ,另外socketio的使用在查阅其它相关文章时有出入,还是尽量以官方文档为准 import VueSocketIO from vue-socket.io import SocketIO from socket.io-…

「Mac畅玩鸿蒙与硬件35」UI互动应用篇12 - 简易日历

本篇将带你实现一个简易日历应用,显示当前月份的日期,并支持选择特定日期的功能。用户可以通过点击日期高亮选中,还可以切换上下月份,体验动态界面的交互效果。 关键词 UI互动应用简易日历动态界面状态管理用户交互 一、功能说明…

【AI系统】推理系统介绍

推理系统介绍 推理系统是一个专门用于部署神经网络模型,执行推理预测任务的 AI 系统。它类似于传统的 Web 服务或移动端应用系统,但专注于 AI 模型的部署与运行。通过推理系统,可以将神经网络模型部署到云端或者边缘端,并服务和处…

Docker 之 bootfs 和 rootfs概述

概述 在 Docker 技术中,理解 bootfs(boot file system)和 rootfs(root file system)的概念对于深入掌握容器技术至关重要。这两个文件系统是 Docker 镜像和容器运行的基础。 bootfs(Boot File System&am…

困扰解决:mfc140u.dll丢失的解决方法,多种有效解决方法全解析

当电脑提示“mfc140u.dll丢失”时,这可能会导致某些程序无法正常运行,给用户带来不便。不过,有多种方法可以尝试解决这个问题。这篇文章将以“mfc140u.dll丢失的解决方法”为主题,教大家有效解决mfc140u.dll丢失。 判断是否是“mf…

M4V 视频是一种什么格式?如何把 M4V 转为 MP4 格式?

M4V 是一种视频文件格式,主要由苹果公司用于其产品和服务中,如 iTunes Store 上的电影和电视节目。这种格式可以包含受版权保护的内容,并且通常与苹果的 DRM(数字版权管理)技术结合使用,以限制内容的复制和…

VS打开UI文件失败

选择一个UI文件,右键打开方式,要自己添加路径 然后选择自己的QT Creator路径 可以参考我的去找一下:"C:\Qt\Qt5.14.2\Tools\QtCreator\bin\qtcreator.exe"

网络编程(UDP\TCP回显服务器)

目录 套接字socket TCP和UDP特点比较 特点 比较 UDP回显服务器/客户端的编写 UDP的socket api 回显服务器 客户端 TCP回显服务器/客户端的编写 TCP的socket api 回显服务器 客户端 优化服务器 1.关闭服务器创建的socket对象 2.引入线程池,为多个客户…

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验三----学校选址与路径规划(超超超详细!!!)

目录 实验三 学校选址与道路规划 3.1 实验内容及目的 3.1.1 实验内容 3.1.2 实验目的 3.2 实验方案 3.3 操作流程 3.3.1 环境设置 3.3.2 地势分析 (1)提取坡度: (2)重分类: 3.3.3 学校点分析 (1)欧氏距离: (2)重分类: 3.3.4 娱乐场所点分析 (1)欧氏距离…

【Delphi】modbus-TCP 协议库

在日常开发中,也会遇到使用modbus的部件,比如温度控制器、读卡器等等,那么使用Delphi开发,也就必须遵守modbus-TCP协议,如果自己使用TCP控件写也没有问题,不过如果有开源的三方库,别人已经调试过…

计算机网络-网络安全

网络安全介绍 端口扫描 安全包括那些方面: 数据存储安全、应用程序安全、操作系统安全、网络安全、物理安全、用户安全教育 一、网络安全问题概述 1. 计算机网络面临的安全性威胁 计算机网络上的通信面临以下的四种威胁: 截获——从网络上窃听他人…

GEE Download Data——气温数据的下载

GEE数据下载第二弹!今天我们来分享气温数据的下载。 一、数据介绍 气温数据我们要用到的是MODIS数据产品,MOD11A2 V6.1 产品提供 1200 x 1200 公里网格内 8 天平均陆地表面温度 (LST)。 MOD11A2 中的每个像素值都是该 8 天内收集的所有相应 MOD11A1 LST 像素的简单平均值。…

【第 1 章 初识 C 语言】1.8 使用 C 语言的 7 个步骤

目录 1.8 使用 C 语言的 7 个步骤 1.8.1 第 1 步:定义程序的目标 1.8.2 第 2 步:设计程序 1.8.3 第 3 步:编写代码 1.8.4 第 4 步:编译 1.8.5 第 5 步:运行程序 1.8.6 第 6 步:测试和调试程序 1.8.…