YOLOv5图像分割中的NMS处理

2023-05-16

在上一篇文章YOLOv5图像分割--SegmentationModel类代码详解有讲到图像经过YOLOv5网络后得到的输出形式,主要是调用了BaseModel类下的forward得到的输出,输出的shape为【batch,25200,117】,这里的25200相当于总的anchors数量【以640*640的输入为例,共有anchors=80*80*3+40*40*3+20*20*3】,117为5[x,y,w,h,conf]+80个类+32【mask的数量】。

那么得到上面这张图的输出后又需要哪些处理呢?又是怎么处理的呢?本篇文章就是来刨析这个问题。

可以从下面的代码看到在进行model后会得到pred和proto。前者就是上面得到图的形式,后者的shape为【batch,32,160,160】,这里的32是mask的数量,160*160是针对80*80这个特征层的上采样得到的。然后是送入NMS进行处理得到新的pred输出。

        pred, proto = model(im, augment=augment, visualize=visualize)[:2]  # im[batch, 3, 640, 640]
        # pred:[batch,25200,117], proto:[batch,32,160,160]
        # NMS
        with dt[2]:
            pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det, nm=32)

目录

NMS中发生了什么?

通过conf_thres进行筛选

xywh2xyxy

取得对应anchor中conf最大的类

NMS处理 


NMS中发生了什么?

那么来看一下NMS中发生了什么 

 可以看到代码中传入的参数为:pred:model的输出,conf_thres:置信度阈值,iou_thres:iou阈值,classes:需要过滤的类,nm为mask的数量。

然后进入内部,prediction的shepe为【batch,25200,117】,因此通过下面的代码得到:

bs:batch size 这里得到是1

nc:117-32-5=80【coco类的数量】

xc:由于prediction在117这个维度的第5维度【这里的4维度】是指conf,所以可以通过conf_thres得到大于阈值的目标mask  xc,那么此时xc的shape为【1,25200】。通过这个步骤就可以将所有anchors中大于conf的目标筛选出来【形式为False or True】

通过conf_thres进行筛选

    bs = prediction.shape[0]  # batch size
    nc = prediction.shape[2] - nm - 5  # number of classes 85-5
    xc = prediction[..., 4] > conf_thres  # candidates 85=5+80=(x,y,w,h,conf) 第4维度为conf

然后新建一个output全零的张量,最后一个通道的shape为6+32=38。6指的【x1,y1,x2,y1,conf,class】。 

output = [torch.zeros((0, 6 + nm), device=prediction.device)] * bs

下面的xi是图像的index,对应该index的图像。

x = x[xc[xi]]:由于prediction当前batch为1 ,所以对应xi此时为0,xc是上面通过conf_thres得到shape为【1,25200】的mask,所以xc[xi]就是取出该batch中所有的anchors【这些anchors内已经内是经过conf筛选的目标】;x的shape为【25200,117】[忘记这个shape的含义可以看我最前面的图],那么x[xc[ix]]就可以表示为通过xc中的25200个含有False or True 的anchors,筛选出conf大于阈值的目标【这个目标维度为117,含有box信息,conf,80个类,32个mask】

在我这里得到新的x的shape为:【52,117】。这就表示了在25200个anchors中有52个anchors内有目标,每个anchor又有117个维度来记录该anchor内目标的boxes信息,conf以及类信息等。

    for xi, x in enumerate(prediction):  # image index, image inference
        # Apply constraints
        # x[((x[..., 2:4] < min_wh) | (x[..., 2:4] > max_wh)).any(1), 4] = 0  # width-height
        x = x[xc[xi]]  # confidence xc是所有anchor内的置信度,shape[1,25200]。表示为:获取当前图像中所有anchor中有预测结果的[这个是通过conf筛选过的]

 下面的这一行代码表示为计算conf,x[:,5:]

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

xywh2xyxy

下面的代码中box是将上面x中的box信息由center_x,center_y,wh转为x1,y1,x2,y2的形式【为后面计算iou做准备】,这里的mi=85【表示mask start index】,因为此时的xshape为【52,117=5+85+32】所以从85开始提取所有的mask。 

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

取得对应anchor中conf最大的类

在下面的代码中x[:,5:mi]=x[:,5:85]表示为取所有anchors中所有类的conf。【0~4是box,5:85是class】,然后取出所有anchors中预测的类中conf最大的conf以及索引j【x[:,5:85]的shape为[52,80],利用max(1,keepdim=True)在80所在的这个维度上取max】,而这里得到最大index j就是每个anchors预测得到的类的index[这样不就知道预测的种类了嘛]。

可视化看一下,这里只展示一部分。前面的一个列是所有anchor得到的最大conf值后面的一列是对应的类别,比如第行中0.24885表示当前这个anchor预测为类别0【也就是persion类,置信度为0.24885】

最后再用cat函数进行拼接,即将box【xyxy】,conf[所有anchor得到最大的conf], j[最大conf对应的类,mask]

    conf, j = x[:, 5:mi].max(1, keepdim=True)
    x = torch.cat((box, conf, j.float(), mask), 1)[conf.view(-1) > conf_thres]

 得到新的x如下图:

下面这行代码是对上面得到x在conf这个维度上进行排序 

x = x[x[:, 4].argsort(descending=True)]  # sort by confidence

NMS处理 

agnostic参数 True表示多个类一起计算nmsFalse表示按照不同的类分别进行计算nms

这里的nms是调用的torchvision下的nms。需要传入boxes,这里的boxes是加了c的偏移量【为什么加这个偏移量这里我没明白,有知道的可以留言说一下】。这里的boxes为【x1,y1,x2,y2】形式。score是已经排序好的,iou_thres是iou阈值。

        # Batched NMS
        c = x[:, 5:6] * (0 if agnostic else max_wh)  # classes
        boxes, scores = x[:, :4] + c, x[:, 4]  # boxes (offset by class), scores
        i = torchvision.ops.nms(boxes, scores, iou_thres)  # NMS

此时得到的i为:tensor([ 0,  2,  6, 16, 30], device='cuda:0')

这里的x是shape为【49,38】,49表示为有目标的49个anchors,38就是前面含有boxes,conf,index,mask的信息。i就是筛选得到的anchors索引。索引得到最终5个anchors以及信息,shape为【5,38】.

output[xi] = x[i]

这个就是我们得到的经过NMS后的输出啦 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

YOLOv5图像分割中的NMS处理 的相关文章

  • SVN 拉取分支(Branch/tag)和SVN合并(Merge)

    合并 xff08 Merge xff09 例子 xff1a 把对feature branch project name v3 3 7 branch的修改合并到develop 步骤1 xff1a 如图 xff0c 右键目标文件夹 xff0c
  • 宏#define的三种基本定义方式:固定值,表达式,运算符。

    define xff1a define是C语言中的预处理命令 xff0c 预处理命令以 开头 xff0c 比如我们经常写的代码 include lt stdio h gt 也是预处理命令 define用于宏定义 xff0c 作用是方便程序段
  • 四旋翼飞行器的姿态解算小知识点

    1 惯性测量单元IMU InertialMeasurement Unit 姿态航向参考系统AHRS Attitude and Heading Reference System 地磁角速度重力MARG Magnetic Angular Rat
  • 四元数姿态解算中的地磁计融合解读

    笔者最近在做四轴 xff0c 涉及到地磁计的融合算法 xff0c 网上大多数是x IMU的融合代码 xff0c 但是这段代码对于地磁计的融合说明没有做过多的解释 xff0c 网上没有相关讨论 xff0c 仅在阿莫论坛看到一篇相关的代码解释
  • C++封装静态链接库及使用

    一 为什么要把程序封装成库 有时我们需要把自己的程序交给第三方调用 xff0c 但是又不想被别人看到自己的具体实现代码 xff0c 就封装成库给别人使用 库有动态链接库和静态链接库 xff0c 区别是动态链接库可以在程序运行时动态链接 xf
  • 四元数姿态的梯度下降法推导和解读

    笔者前面几篇文章讨论的是基于四元数的互补滤波算法 xff0c 并单独对地磁计融合部分做了详细的讨论和解释 而本文讨论的姿态融合算法叫做梯度下降法 xff0c 这部分代码可以参见Sebastian O H Madgwick在2010年4月发表
  • 四轴加速度计滤波

    加速度计滤波实验参数 xff1a 采样频率Fs 61 250Hz 截止频率Cutoff Frequency 未开电机静止 开电机悬停 未开电机转动飞控 原始输出 Raw 260 Hz 260Hz 260Hz MPU6050内部 LPF 94
  • Kalman论文笔记

    笔者前段时间阅读了一些关于Kalman的姿态论文 xff0c 本想把Kalman的知识点也整理出来发布 xff0c 无奈这编辑器不给力 xff0c 太多的公式无法复制粘贴 xff0c 图片格式上传的太复杂 xff0c 就放弃了 因此笔者只发
  • uCOS-III学习笔记

    前一段时间笔者学习uCOS III xff0c 第一次接触OS这个概念吧 下面把个人的学习笔记分享出来 xff0c 仅供参考 1 前后台系统 xff1a 后台程序是一个死循环 xff0c 也称为 任务级 xff0c 前台程序则是中断服务程序
  • 3.17 开发一个插件

    打开动态链接库 void dlopen const char filename int flag 返回一个操作句柄void Handle 61 dlopen libct so RTLD LAZY RTLD LAZY xff1a 解析动态库遇
  • 5.7 属性声明

    5 7 属性声明 主要用途 使用 attribute 来声明变量 函数的特殊属性 指导编译器来进行特定方面的优化或代码检查 使用方法 在声明后面添加 xff1a attribute ATTRIBUTE 例 xff1a int global
  • 8.18 模块设计原则:高内聚低耦合

    8 18 模块设计原则 xff1a 高内聚低耦合 模块内聚 定义 xff08 软考 xff09 块内联系 xff1a 模块内各元素的关联 交互程度 从功能角度 xff1a 自己的功能自己实现 xff0c 不麻烦其它模块 如何实现高内聚 功能
  • 9.12 中断(下):中断函数的编写

    9 12 中断 下 xff1a 中断函数的编写 中断特性 可随时打断正在执行的任务 可在任何地方打断正在执行的任务 中断返回后 xff0c CPU不一定重新执行被打断的任务 中断函数 调用时间不固定 xff1a 中断要自己保护现场 调用地点
  • 9.16 内存、外存与外设

    9 16 内存 外存与外设 按速度排列 寄存 缓存 内存 外存 存储分类 内存 又称主存 xff1a CPU能直接寻址的存储空间 存取速度快 包括 xff1a RAM ROM cache等 外存 又称辅存 xff1a 除CPU缓存和内存以外
  • 载波相位测量原理

    1 重建载波 定义 xff1a 载波调制了电文之后变成了非连续的波 xff0c 将非连续的载波信号恢复成连续的载波信号 码相关法 xff1a 方法 将所接收到的调制信号 xff08 卫星信号 xff09 与接收机产生的复制码相乘 技术要点
  • wpa_suplicant 详解 文章收集

    wpa suplicant 详解 文章收集 参考资料 https w1 fi wpa supplicant devel index html https zhuanlan zhihu com p 24246712 https www cnb
  • 玩转AOSP源码编译

    整理搬运一下大佬的文章 https www bilibili com video BV19f4y1r7E6 http liuwangshu cn batcoder aosp 3 compiling aosp html 1 前言 1 1 re
  • Qt 64位链接 mysql8.0 中出现的问题及其解决办法

    1 driver not loaded 原因总结 MinGW编译器中找不到 MySql驱动或者驱动位数不对MinGW编译器找不到 MySql动态库或者动态库有问题代码写的有问题 https blog csdn net l0p0c artic
  • Linux man 手册中各种括号的含义

    尖括号 lt gt 一般用于表示必选项或者参数的占位符 xff0c 实际使用时需要替换成具体的值 方括号 一般用于表示可选项或者参数的占位符 xff0c 实际使用时可以选择是否包含该选项或者参数 大括号 一般用于表示一组选项或者参数 xff
  • 批量创建 markdown 文件的脚本

    写一个 dos脚本 xff0c 其功能是创建 36 个 以 34 Linux内核编程 ch11 sec 34 为开头的 Markdown格式的文件 64 echo off chcp 65001 setlocal enabledelayede

随机推荐

  • libcurl库的http get和http post使用

    一 libcurl中的http get使用方法 1 为什么要使用libcurl 1 作为http的客户端 xff0c 可以直接用socket连接服务器 xff0c 然后对到的数据进行http解析 xff0c 但要分析协议头 xff0c 实现
  • Postman查看完整的请求报文

    第一步 工具栏 View gt Show postman console 第二步 点击 Show Postman Console 之后 就会弹出一个如下图所示的界面 小窍门 postman可以把请求的参数生成代码 可以在代码使用 仅仅只需点
  • 通用异步接收器/发送器(UART)——发送与接收

    图1 带数据总线的UART UART代表通用异步接收器 发送器 它不是像SPI和I2C这样的通信协议 xff0c 而是微控制器中的物理电路或独立的IC UART的主要目的是发送和接收串行数据 关于UART最好的一点是其仅使用两条线在设备之间
  • MYSQL导入数据出现Error 1290:The MySQL server is running with the --secure-file-priv option so it cannot ex

    最近在学习MySQL xff0c 刚入门 xff0c 在导入数据的时候出现了Error 1290 xff1a The MySQL server is running with the secure file priv option so i
  • openmv--无人机通过mavlink实现apriltag定点降落

    span class token comment 无人机通过mavlink实现apriltag定点降落例程 span span class token comment span span class token comment 这个脚本使用
  • [转] 用WWW-Authenticate实现登录验证

    用WWW Authenticate实现登录验证 文章来源 xff1a http www keakon cn bbs thread 1989 1 1 html 今天在研究HTTP协议时发现一个叫WWW Authenticate的头字段 xff
  • ROS--坐标理解

    北东地坐标系 NED north east down 东北天 ENU east north up 机体坐标系 body frame 载体坐标系 是以载体为中心 xff0c 主要作用是处理与传感器直接测得的物理量 导航坐标系 可以是地固坐标系
  • qt 编译qgc常见问题

    qt LINK warning LNK4098 默认库 MSVCRT 与其他库的使用冲突 xff1b 请使用 NODEFAU 如果以前没有问题 xff0c 突然出现的这个问题 xff0c 绝大可能是中间编译过程太多造成的 清理项目 重新构建
  • VINS-FUSION-GPU在jetson nx上的实现

    需要安装经过修改的Ubuntu18系统 https span class token operator span span class token comment developer nvidia com zh cn embedded do
  • 主机ping通虚拟机,虚拟机ping通主机解决方法(NAT模式)

    主机ping通虚拟机 xff0c 虚拟机ping通主机解决方法 xff08 NAT模式 xff09 有时候需要用虚拟机和宿主机模拟做数据交互 xff0c ping不通是件很烦人的事 xff0c 本文以net模式解决这一问题 宿主机系统 xf
  • 一个基于Matlab的简单Gui设计

    前几日浩子说要编一个基于Matlab的用户图像界面 xff0c 他用GUIDE搭了一个大概的框架 xff0c 大概要实现数据读入 做图分析 图像清除 关闭界面的功能 xff0c 我用函数形式给改编了一个 xff0c 虽然问题比较简单 xff
  • 关于N步相移中相位噪声仿真分析的一点说明

    在条纹投影的三维测量中 xff0c 有这么一个经典的结论 xff1a 假设光强的噪声为方差为 2 xff0c 那么 xff0c 经过N步标准相移求得的相位的方差为2 2 N B 2 xff08 xff09 xff0c 其中 xff0c B为
  • 如何给MFC对话框添加背景图片

    一 创建项目 文件 新建项目 MFC应用程序 该页面使用 基于对话框 完成即可 注意 取消 使用Unicode库 否则在使用AfxMessageBox会报错 xff0c 没有一个可以转换的参数类型 xff0c 要加AfxMessageBox
  • 如何检测应用程序调用了哪些DLL文件?

    之前所用的检测工具是Dllshow xff0c 后来突然不能用了 xff0c VS以前有Depends xff0c 后来高级版本也没了 最近找到一种简单方便的方法 xff0c 利用windowsx系统自带的功能 运行你想知道的应用程序 xf
  • 网络编程懒人入门(一):快速理解网络通信协议(上篇)

    1 写在前面 论坛和群里常会有技术同行打算自已开发IM或者消息推送系统 xff0c 很多时候连基本的网络编程理论 xff08 如网络协议等 xff09 都不了解 xff0c 就贸然定方案 写代码 xff0c 显得非常盲目且充满技术风险 即时
  • Matlab中调用C++dll

    利用mex技术可以实现这个功能 xff0c 但是必须例外写一个接口函数 xff0c 比较麻烦 利用dll调用的方法 xff0c 简单方便 下面就以实现加法函数add 为例 xff0c 来详细介绍具体过程 一 利用VS生成dll文件 利用VS
  • 大小端序与端序转换

    最近在做客户项目的时候 xff0c 遇到了不同厂家的安防相机输出的数据大小端序不一致的情况 xff0c 导致在使用同一种方式处理时 xff0c 出现了错误 虽然问题已经解决 xff0c 还是顺手把大小端序的知识简单梳理一下 1 大端序和小端
  • debian ware source

    deb http ftp cn debian org debian jessie main non free contrib deb http ftp cn debian org debian jessie proposed updates
  • debian中文输入法——拼音和五笔的解决方法

    最近安装Debian操作系统 xff0c 但遇到一个重大的困惑 xff0c 那就是为什么Debian菜单里面有一个Fcitx的选项 xff0c 但是为什么就是无法调出前端来实现输入 xff0c 这是个大问题 xff0c 于是就研究 xff0
  • YOLOv5图像分割中的NMS处理

    在上一篇文章YOLOv5图像分割 SegmentationModel类代码详解有讲到图像经过YOLOv5网络后得到的输出形式 xff0c 主要是调用了BaseModel类下的forward得到的输出 xff0c 输出的shape为 batc