人工智能图像分割之Mask2former源码解读

news/2025/2/9 5:57:37/

环境搭建:

(1)首先本代码是下载的mmdetection-2022.9的,所以它的版本要配置好,本源码配置例如mmcv1.7,python3.7,pytorch1.13,cuda11.7。pytorch与python,cuda版本匹配可参考:https://www.jb51.net/python/3308342lx.htm。

(2)还有一个是先要安装一个vs2022版本或vs2019,其中确保工作负载下"使用C++的桌面开发"的内容基本安装上

(3)数据集就用coco集,在参数配置中指定目录,例如../configs/mask2former目录下的.py文件

一.Backbone获取多层级特征

(1)进入train.py读取各个配置参数,构建模型调用Mask2Former类,如下图:

有了model(Mask2Former),datasets(COCO数据集)和cfg后就传入下面的方法:

(2)进入Mask2Former模块,然后调用MaskFormer模块,如下图:

(3)进入MaskFormer类中,并进入def forward_train这个方法中,如下图:

然后

进入父类BaseDetector的forward_train方法:

回到maskformer.py中,如下图:

(4)进入head层,因为mask2former_head的父类是maskformer_head,所以会先调父类中的forward_train方法后再进入到了mask2former_head中的forward方法中,mask2former_head.py这个类很重要,如下图: 

二.多层级采样点初始化构建

对输入的每一张特征图加上位置编码,这个FOR中的特征图是256

上图中得到的level_embed就是按每个层级取出的值,它是一个256维的向量,下面用view转成四维向量后与位置编码(pos_embed)做加法。

然后调用point_generator中的single_level_grid_priors方法,如下图:

shift_x与shift_y都是32的一维矩阵,

做成网络后就是32*32=1024的一维矩阵,然后做合并得到棋盘上的位置

返回到msdeformattn_pixel_decoder.py中,如下图:

它是维度转变后1024在最前面的

三.多层级输入特征序列创建方法

上图中的所说的是进入transformer.py中的DetrTransformerEncoder类下的forward方法。

四.偏移量与权重计算并转换

还是在transformer.py中,对每一层(例如selfattention,bn,norm,ffn,全连接)进行for,如果是self_attn

执行selfattention层时,进入到了multi_scale_deform_attn.py中,

进入到multi_scale_deform_attn.py中的forward方法:

下面做了多头注意力机制,变成8头:

重点来了,对query做sampling_offsets与attention_weights方法后并调用view变形得到相应的每个点的偏移量与权重(softmax),偏移量到时候做采样时用到,最后还要对这二个值做乘法,如下图:

其中sampling_offsets这个是全连接层,如下图:

由这4个采样点找它们的偏移量,每个偏移量都有x,y二个值组成。

为什么这里权重值是96呢?因为每个偏移量是一个点,它只是这个点有x,y组成,但权重是指这个点的权重,所以就是上面偏移量输出的192/2=96了(也等以8*(3*4)=8*12)。

上图中的levels是指层级数,points是指采样点数。

五.Encoder特征构建方法实例

偏移量有了,现在我们执行特征计算操作了,而原来特征不准,现在要把新的偏移完的准确的特征拿到手,所以这里也要做特征的偏移。还是在multi_scale_deform_attn.py中,

上图中对齐特征是要重新进行采样的,这里的特征偏移范围是[-1,1]。

做完这一步后返回到transformer.py这里,发现就是做了一个self_attn层的操作,得到query值,如下图所示:

做完ffn全连接后再做norm,就算做完一个层级采样了,其它层级采样也是一样按这样流程的,最后把每一层级执行完后就得到特征值,返回到msdeformattn_pixel_decoder.py中,存到了“(3)多层级输入特征序列创建方法”所说的memory变量(它存的是编码完后特征)中,如下图:

总结一下这里encoder是做了什么:其实就是和可变形detr是一样的,就是对展开的序列提特征,我们是希望它是多层级,多头注意力机制和加上可变形的位置偏移,这样可以得到我们序列更好的特征。

还是在msdeformattn_pixel_decoder.py中,总共3个层级,每个层级的大小(图像上的点的个数)分别是1024(它是由32*32得到),4096(它是由64*64得到)与16384(它是由128*128得到)如下图:

等下就用这个y用来预测一下是每个点是前景还是背景?

六.query要预测的任务解读

返回到mask2former_head.py类中,至此self.pixel_decoder方法调用结束(主要是transformer编码这一块),准备decoder解码了。

上图的query_feat中初始化的100是指decoder中会找100样东西,例下图:

下面开始调用forward_head方法:

这个会找到这100个的前景与背景分别是那些?

七.Decoder中的AttentionMask方法

上图中调用sigmoid()后的值是在0至1之间范围之间。

返回上面3张图的预测值

现在又跳回到transformer.py的baseTransformer当中,

八.损失模块输入参数分析

返回到mask2former_head.py中,如下图:

有了cls_pred_list,mask_pred_list这二个结果(10层)后,接下来就去计算每一层的损失函数结果了。返回到maskformer_head.py文件中,如下图:

上图中的81=80+1,其中80是实际类别,1表示背景。

gt_masks是指标注的信息。

九.标签分配策略解读

进入到mask2former_head.py中的loss_single方法中,它是对每一层进行处理(共10层),

get_targets方法目的就是找正负样本,这个方法是在maskformer_head.py中,对于每一张图像它的正负样本是不一样的。

调用上图的multi_apply会进入到mask_hungarian_assigner.py中的assign方法,这里主要进行标签分配,如下图:

上图100个-1的值当中,如果与标签匹配上就修改里面-1值。

上图中标签分配考虑的三方面其实就对应分类,mask,iou这三方面的损失。

十.正样本筛选损失计算

还是在mask_hungarian_assigner.py中,

上图中的gt_labels是10个标签。调用cls_cost方法后会进入到match_cost.py中,如下图:

上图中调用了softmax方法后即把cls_pred变成概率值了(0------1之间的值),

同时cls_cost的第2个维度是10了,即返回值变成了(100,10),cls_cost的值是负数来的,因为前面加了负号,如下图:

mask_hungarian_assigner.py中计算完类别损失后,现在计算mask损失,如下图:

上图中的12544就当作服从256*256正态分布的随机采样吧,调用上图的mask_cost方法后进入下图的类中:

上图中求pos与neg损失时,都调用了binary_cross_entropy_with_logits,首先我们知道二元交叉熵(Binary cross entropy)是二分类中常用的损失函数,它可以衡量两个概率分布的距离,二元交叉熵越小,分布越相似。相比F.binary_cross_entropy函数,F.binary_cross_entropy_with_logits函数在内部使用了sigmoid函数,也就是F.binary_cross_entropy_with_logits = sigmoid + F.binary_cross_entropy。

上图中因为它是有12544个采样点,它是累加后求平均,所以要除以12544,最后得到一个(100,10)的矩阵返回回去。为什么它是返回(100,10)?是因为它是100个query都分别与10个类别去计算得到的。

十一.标签分类匹配结果分析

这个mask算出来的cost值是正数来的。下面开始计算dice_cost(类似iou重合比例计算)

跳转到match_cost.py中,先拉长,再按dice系数公式得到被除数

Dice 系数可以计算两个字符串的相似度:Dice(s1,s2) = 2*comm(s1,s2)/(leng(s1)+leng(s2))。其中,comm(s1,s2) 是s1和s2中相同字符的个数; leng(s1)、leng(s2)是字符串s1、s2 的长度。

返回后得到如下图:

计算出三个损失值后就进行累加,如下图:

而上图中matched_col_inds的10个索引值是对应gt标签中的索引位置,matched_row_inds是100个中匹配到损失最小的对应的10个索引。这时我们就认为通过与标签匹配完成了,得到正样本了。

返回后回到了mask2former_head.py中,调用assign方法进行标签匹配就结束了,如下图:

然后调用sample主要是用来取正,负样本的索引值,如下图:

上图中mask_targets是只考虑匹配上的10个。到此时,第一张图片就处理完了,然后按上面的逻辑做第二张图片的处理了。

十二.最终损失计算流程

这时(9)中所说的调用get_targets方法就结束了。前面算的损失是关于标签分配的。而下面将算实际的损失了。

上图中labels这个标签是更新了正样本索引后的标签值,80是默认的初始化的负样本索引。上图中这三个都是200,那就可以做交叉熵损失了,调下图的方法self.loss_cls方法。

上图中二个极端值是指概率值(上图画的y轴值)要么靠近0,要么靠近1,这样就表示确定性越大(高),而不确定性越强的是概率值靠近0.5那种。

十三.汇总所有损失完成迭代

get_uncertainty方法返回就得到不确定性的点索引,如下图

在分割中也许是边界点比较模拟二可(即可能是背景也可能是前景),它的不确定性就比较高。

这里三个loss_cls,loss_dice,loss_mask做完返回值,重复迭代10次求这三个值。


http://www.ppmy.cn/news/1570514.html

相关文章

【模型部署】大模型部署工具对比:SGLang, Ollama, VLLM, LLaMA.cpp如何选择?

在选择大模型部署工具时,需要考虑多个因素,包括性能、支持的语言和模型、硬件支持、易用性以及社区支持等。以下是对比分析: 性能 VLLM (Virtual Tensor Language): VLLM 是一个高性能的推理库,特别适用于长序列任务。它通过虚…

Day38【AI思考】-彻底打通线性数据结构间的血脉联系

文章目录 **彻底打通线性数据结构间的血脉联系****数据结构家族谱系图****一、线性表(老祖宗的规矩)****核心特征** **二、嫡系血脉解析**1. **数组(规矩森严的长子)**2. **链表(灵活变通的次子)** **三、庶…

【Maven】项目管理工具-Maven

目录 1. Maven简介 1.1 项目管理 1.2 项目构建 1.3 项目构建工具 1.4 Maven的四大特征 1.4.1 依赖管理系统 1.4.2 多模块构建 1.4.3 一致的项目结构 1.4.4 一致的构建模型和插件机制 1.5 Maven模型 ​编辑 2.maven的安装配置 2.1 Maven的安装配置 2.1.1检测jdk的版…

C++RAII用法

思维导图 为什么要引入RAII 有一个简单的服务器例子。在Windows系统上写一个C程序,在客户端请求连接时,给客户端发一条"Hello World"消息,然后关闭连接。不需要保证客户端一定能收到。 程序实现流程 创建socket绑定IP地址和端口…

nas-群晖docker查询注册表失败解决办法(平替:使用SSH命令拉取ddns-go)

目录 前言必读 一、遇到问题 二、操作步骤 (一)打开群晖系统的SSH服务? (二)Windows电脑本地下载安装putty? 输入登录账号密码 开启root权限 例子:使用命令行下载ddns-go? 前言必读 读者手册(必…

【JVM详解一】类加载过程与内存区域划分

一、简介 1.1 概述 JVM是Java Virtual Machine(Java虚拟机)的缩写,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。由一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域等组成。JVM屏蔽了与操作系统平台相关…

MoviePy,利用Python自动剪辑tiktok视频

Python剪辑视频是非常强大的,而且能流水线批量操作,可以使用MoviePy库实现。 最近看到一个Github项目,作者利用Python写了一个自动生成tiktok视频的脚本,受到热捧。 现在像抖音、tiktok上有很多流水线生产的视频,不少…

RNN-day1-NLP基础

NLP基础 一、基本概念 自然语言处理:Natural Language Processing,主要目标是让计算机能够理解、解释和生成人类语言的数据。 1 基本概念 1.1NLP概念 语言:人类沟通的机构化系统,包括声音、书写符号、手势 自然语言:自然进化…