欢迎来到皮皮网网首页

【下载网站的源码】【monkey源码位置】【底部启动指标源码】实例分割源码_实例分割源码怎么用

来源:柳州打车app源码 时间:2024-11-24 15:49:45

1.PyTorch 源码分析(三):torch.nn.Norm类算子
2.实例分割之BlendMask
3.ForkjoinPool -1
4.使用mmdeploy部署rtmdet ins做实例分割
5.[按键源码分享]----QUI列表框显示脚本TracePrint输出信息
6.MaskFormer源码解析

实例分割源码_实例分割源码怎么用

PyTorch 源码分析(三):torch.nn.Norm类算子

       PyTorch源码详解(三):torch.nn.Norm类算子深入解析

       Norm类算子在PyTorch中扮演着关键角色,实例实例它们包括BN(BatchNorm)、分割分割LayerNorm和InstanceNorm。源码源码用

       1. BN/LayerNorm/InstanceNorm详解

       BatchNorm(BN)的实例实例核心功能是对每个通道(C通道)的数据进行标准化,确保数据在每个批次后保持一致的分割分割尺度。它通过学习得到的源码源码用下载网站的源码gamma和beta参数进行缩放和平移,保持输入和输出形状一致,实例实例同时让数据分布更加稳定。分割分割

       gamma和beta作为动态调整权重的源码源码用参数,它们在BN的实例实例学习过程中起到至关重要的作用。

       2. Norm算子源码分析

       继承关系:Norm类在PyTorch中具有清晰的分割分割继承结构,子类如BatchNorm和InstanceNorm分别继承了其特有的源码源码用功能。

       BN与InstanceNorm实现:在Python代码中,实例实例BatchNorm和InstanceNorm的分割分割实例化和计算逻辑都包含对输入数据的2D转换,即将其分割为M*N的源码源码用矩阵。

       计算过程:在计算过程中,首先计算每个通道的均值和方差,这是这些标准化方法的基础步骤。

       C++侧的源码洞察

       C++实现中,对于BatchNorm和LayerNorm,代码着重于处理数据的标准化操作,同时确保线程安全,通过高效的数据视图和线程视图处理来提高性能。

实例分割之BlendMask

       沈春华老师团队的最新研究文章,名为“BlendMask”,旨在通过巧妙融合底层语义信息和实例层信息,提升模型效果。研究主要贡献在于设计了一个创新的Blender模块,受到top-down和bottom-up方法的启发。

       BlendMASK的网络结构包含三个关键部分,尽管论文中的monkey源码位置图示可能不够直观,需要结合论文和源码深入了解。Bottom模块输出特征的维度为N*K*H/s*W/s,其中N表示批次大小,K是基础数量,H*W是输入尺寸,S是得分输出步长。

       Top层在检测输出时,通过额外的卷积层生成注意力A,其维度为N*(K'M'M)*Hl*Wl,其中M值较小,仅比传统top-down方法小。Blender模块利用注意力和位置敏感的基础来生成最终预测。

       实验部分详尽,如对比不同融合特征策略(Blender vs. YOLACT vs. FCIS)、分辨率设置、基础数量K的选择以及特征提取位置等,作者充分展示了其设计的消融实验。论文强调,尽管没有采用FCOS,但实际效果显著,理解它需要对YOLACT、RPN和DeeplabV3+的核心思想有深入理解。

       总的来说,这篇文章以工程应用为导向,提供了宝贵的实践指导,对于学术研究和实际项目具有很高的参考价值。

ForkjoinPool -1

        ForkJoin是用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。

        下面是一个是一个简单的Join/Fork计算过程,将1—数字相加

        通常这样个模型,你们会想到什么?

        Release Framework ? 常见的处理模型是什么? task pool - worker pool的模型。 但是Forkjoinpool 采取了完全不同的模型。

        ForkJoinPool一种ExecutorService的实现,运行ForkJoinTask任务。ForkJoinPool区别于其它ExecutorService,主要是因为它采用了一种工作窃取(work-stealing)的机制。所有被ForkJoinPool管理的线程尝试窃取提交到池子里的任务来执行,执行中又可产生子任务提交到池子中。

        ForkJoinPool维护了一个WorkQueue的数组(数组长度是2的整数次方,自动增长)。每个workQueue都有任务队列(ForkJoinTask的数组),并且用base、top指向任务队列队尾和队头。work-stealing机制就是工作线程挨个扫描任务队列,如果队列不为空则取队尾的任务并执行。示意图如下

        流程图:

        pool属性

        workQueues是pool的属性,它是WorkQueue类型的数组。externalPush和externalSubmit所创建的workQueue没有owner(即不是worker),且会被放到workQueues的偶数位置;而createWorker创建的workQueue(即worker)有owner,且会被放到workQueues的奇数位置。

        WorkQueue的几个重要成员变量说明如下:

        这是WorkQueue的config,高位跟pool的config值保持一致,而低位则是workQueue在workQueues数组的位置。

        从workQueues属性的介绍中,我们知道,不是所有workQueue都有worker,没有worker的workQueue称为公共队列(shared queue),config的第位就是用来判断是否是公共队列的。在externalSubmit创建工作队列时,有:

        q.config = k | SHARED_QUEUE;

        其中q是新创建的workQueue,k就是q在workQueues数组中的位置,SHARED_QUEUE=1<<,注意这里config没有保留mode的信息。

        而在registerWorker中,则是这样给workQueue的config赋值的:

        w.config = i | mode;

        w是新创建的workQueue,i是其在workQueues数组中的位置,没有设置SHARED_QUEUE标记位

        scanState是workQueue的属性,是int类型的。scanState的低位可以用来定位当前worker处于workQueues数组的哪个位置。每个worker在被创建时会在其构造函数中调用pool的registerWorker,而registerWorker会给scanState赋一个初始值,这个值是奇数,因为worker是由createWorker创建,并会被放到WorkQueues的奇数位置,而createWorker创建worker时会调用registerWorker。

        简言之,worker的scanState初始值是奇数,非worker的scanstate初始值=INACTIVE=1<<,小于0(非worker的workQueue在externalSubmit中创建)。

        当每次调用signalWork(或tryRelease)唤醒worker时,worker的高位就会加1

        另外,scanState<0表示worker未激活,当worker调用runtask执行任务时,scanState会被置为偶数,即设置scanState的最右边一位为0。

        worker休眠时,是这样存储的

        worker的唤醒类似这样:

        在worker休眠的4行伪码中,让ctl的低位的值变为worker.scanState,这样下次就可以通过scanState唤醒该worker。唤醒该worker时,把该worker的preStack设置为ctl低位的值,这样下下次唤醒的worker就是scanState等于该preStack的worker。

        这里通过preStack保存下一个worker,这个worker比当前worker更早地在等待,所以形成一个后进先出的栈。

        runState是int类型的值,控制整个pool的运行状态和生命周期,有下面几个值(可以好几个值同时存在):

        如果runState值为0,表示pool尚未初始化。

        RSLOCK表示锁定pool,当添加worker和pool终止时,就要使用RSLOCK锁定整个pool。如果由于runState被锁定,导致其他操作等待runState解锁(通常用wait进行等待),当runState设置了RSIGNAL,表示runState解锁,并通知(notifyAll)等待的操作。

        剩下4个值都跟runState生命周期有关,都可以顾名思义:

        当需要停止时,设置runState的STOP值,表示准备关闭,这样其他操作看到这个标记位,就不会继续操作,比如tryAddWorker看到STOP就不会再创建worker:

        而tryTerminate对这些生命周期状态的处理则是这样的:

        当前top和base的初始值为 INITIAL_QUEUE_CAPACITY >>>1= (1 << )>>>1 = /2。然后push一个task之后,top+=1,也就是说,top对应的位置是没有task的,最近push进来的task在top-1的位置。而base的位置则能对应到task,base对应最先放进队列的task,top-1对应最后放进队列的task。

        qlock值含义:1: locked, < 0: terminate; else 0

        即当qlock值位0时,可以正常操作,值=1时,表示锁定

        int SQMASK=0xe,则任何整数跟SQMASK位与后,得到的数就是偶数。

        证明:

        注意这里化为二进制是 ,尤其注意最右边第一位是0,任何数跟最右边第一位是0的数位与后,得到的数就是偶数,因为位与之后,第一位就是0,比如s=A&SQMASK,A可以是任意整数,然后把s按二进制进行多项式展开,则有s=2 n1+2 n2 ……+2^nn,这里n≥1,所以s可以被2整除,即s是偶数。

        所以一个数是奇数还是偶数,看其最右边第一位即可。

        我们知道workQueue有externalPush创建的和createWorker创建的worker,两种方式创建的workQueue,其放置到workQueues的位置是不同的,前者放到workQueue的偶数位置,而后者则放到奇数位置。不同workQueue找到自己在workQueues的位置的算法有点不同。

        下面看一下forkjoin框架获取workQueues中的偶数位置的workQueue的算法:

        这样就能获取workQueues的偶数位置的workQueue。m保证m & r & SQMASK这整个运算结果不会超出workQueues的下标,SQMASK保证取到的是偶数位置的workQueue。这里有一个有趣的现象,假设0到workQueues.length-1之间有n个偶数,m & r & SQMASK每次都能取到其中一个偶数,而且连续n次取到的偶数不会出现重复值,散列性非常好。而且是循环的,即1到n次取n个不同偶数,n+1到2n也是取n次不同偶数,此时n个偶数每个都被重新取一次。下面分析下r值有什么秘密,为何能保证这样的散列性

        ThreadLocalRandom内有一常量PROBE_INCREMENT = 0x9eb9,以及一个静态的probeGenerator =new AtomicInteger() ,然后每个线程的probe= probeGenerator.addAndGet(PROBE_INCREMENT)所以第一个线程的probe值是0x9eb9,第二个线程的值就是0x9eb9+0x9eb9,第三个线程的值就是0x9eb9+0x9eb9+0x9eb9以此类推,整个值是线性的,可以用y=kx表示,其中k=0x9eb9,x表示第几个线程。这样每个线程的probe可以保证不一样,而且具有很好的离散性。

        实际上,可以不用0x9eb9这个值,用任意一个奇数都是可以的,比如1。如果用1的话,probe+=1,这样每个线程的probe就都是不同的,而且具有很好的离散性。也就是说,假设有限制条件probe<n,超过n则产生溢出。则probe自加n次后才会开始出现重复值,n次前probe每次自加的值都不同。实际上用任意一个奇数,都可以保证probe自加n次后才会开始出现重复值,有兴趣可看本文最后附录部分。由于奇数的离散性,所以只要线程数小于m或者SQMASK两者中的最小值,则每个线程都能唯一地占据一个ws中的一个位置

        当一个操作是在非ForkjoinThread的线程中进行的,则称该操作为外部操作。比如我们前面执行pool.invoke,invoke内又执行externalPush。由于invoke是在非ForkjoinThread线程中进行的(这里是在main线程中进行),所以是一个外部操作,调用的是externalPush。之后task的执行是通过ForkJoinThread来执行的,所以task中的fork就是内部操作,调用的是push,把任务提交到工作队列。其实fork的实现是类似下面这样的:

        即fork会根据执行自身的线程是否是ForkJoinThread的实例来判断是处于外部还是内部。那为何要区分内外部?

        任何线程都可以使用ForkJoin框架,但是对于非ForkJoinThread的线程,它到底是怎样的,ForkJoin无法控制,也无法对其优化。因此区分出内外部,这样方便ForkJoin框架对任务的执行进行控制和优化

        forkJoinPool.invoke(task)是把任务放入工作队列,并等待任务执行。源码如下

        这里externalPush负责任务提交,externalPush源码如下:

使用mmdeploy部署rtmdet ins做实例分割

       在尝试使用mmdeploy部署rtmdet ins进行实例分割时,发现网上资源较少,github的问题也有不少未解决,只得自己动手,底部启动指标源码留作档案。

       构建时需严格遵循源代码构建流程,从下载到构建,避免第三方库问题。

       ppl.cv不支持cuda,构建时需在cuda.cmake中设置与自己显卡对应的flag。

       使用了最新版的tensorrt和cudnn,版本对运行结果影响不大,但确保环境变量已正确设置。

       安装mmcv时需注意版本,应使用大于2.0.0、小于2.2.0的版本,直接按照教程安装易导致版本2.3.0,mmdet会报错,我选择安装2.1.0版本。

       在使用中需注意cuda版本,选择.x版本最为合适。

       因为mmdeploy需要nvcc进行编译,所以本地的cuda toolkit也应安装。我忽视了这一点,nvcc编译可以正常通过,但在运行时在trt nms处出现错误。

       在修改permuteData.cu文件后,发现问题是由于sm_不兼容(我的显卡是,查看主机cuda版本是否支持)。吐槽的是,即使卸载过cuda导致nvcc版本为.1,编译也能通过!

       如果你的cuda版本高于.x,请修改zsh/bash指定版本,短信轰炸 java源码先执行,再添加到环境变量。

       在模型转换时,需要将mmdetection的_base_文件夹导入到mmdeploy的_base_中,将mmdetection的/config/rtmdet导入到mmdeploy的/config中,否则会找不到type。

[按键源码分享]----QUI列表框显示脚本TracePrint输出信息

       展示效果:

       当Form1加载完成时

       Form1中的ListBox1列表为空

       初始化日志记录并输出信息

       再次初始化日志记录并输出信息

       定义函数处理日志记录

       读取文件"C:\a.log"内容

       解析文件内容,去掉换行符并分割

       将解析结果加入ListBox1列表中

       函数结束

       若需获取源码实例,推荐关注按键精灵论坛,知乎账号,微信公众号“按键精灵”。

       如有疑问,可留言或私信。具体内容可点击查看。

MaskFormer源码解析

       整个代码结构基于detectron2框架,代码逻辑清晰,从配置文件中读取相关变量,无需过多关注注册指令,核心在于作者如何实现网络结构图中的关键组件。MaskFormer模型由backbone、sem_seg_head和criterion构成,backbone负责特征提取,sem_seg_head整合其他部分,criterion用于计算损失。

       在backbone部分,作者使用了resnet和swin两种网络,关注输出特征的键值,如'res2'、'res3'等。在MaskFormerHead中,android源码结构分析核心在于提供Decoder功能,这个部分直接映射到模型的解码过程,通过layers()函数实现。

       pixel_decoder部分由配置文件指定,指向mask_former/heads/pixel_decoder.py文件中的TransformerEncoderPixelDecoder类,这个类负责将backbone提取的特征与Transformer结合,实现解码过程。predictor部分则是基于TransformerPredictor类,负责最终的预测输出。

       模型细节中,TransformerEncoderPixelDecoder将backbone特征与Transformer结合,生成mask_features。TransformerEncoderPixelDecoder返回的参数是FPN结果与Transformer编码结果,后者通过TransformerEncoder实现,关注维度调整以适应Transformer计算需求。predictor提供最终输出,通过Transformer结构实现类别预测与mask生成。

       损失函数计算部分采用匈牙利算法匹配查询和目标,实现类别损失和mask损失的计算,包括dice loss、focal loss等。整个模型结构和输出逻辑清晰,前向运算输出通过特定函数实现。

       总的来说,MaskFormer模型通过backbone提取特征,通过Transformer实现解码和预测,损失函数计算统一了语义分割和实例分割任务,实现了一种有效的方法。理解代码的关键在于关注核心组件的功能实现和参数配置,以及损失函数的设计思路。强烈建议阅读原论文以获取更深入的理解。

Python3基础

        默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串。 当然你也可以为源码文件指定不同的编码:

        在 Python 3 中,非 ASCII 标识符也是允许的了。

        保留字即关键字,我们不能把它们用作任何标识符名称。Python 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字:

        Python中单行注释以 # 开头,实例如下:

        执行以上代码,输出结果为:

        多行注释可以用多个 # 号,还有 ''' 和 """:

        执行以上代码,输出结果为:

        python最具特色的就是使用缩进来表示代码块,不需要使用大括号 { } 。

        缩进的空格数是可变的,但是同一个代码块的语句必须包含相同的缩进空格数。实例如下:

        以下代码最后一行语句缩进数的空格数不一致,会导致运行错误:

        以上程序由于缩进不一致,执行后会出现类似以下错误:

        Python 通常是一行写完一条语句,但如果语句很长,我们可以使用反斜杠()来实现多行语句,例如:

        在 [], { }, 或 () 中的多行语句,不需要使用反斜杠(),例如:

        python中数字有四种类型:整数、布尔型、浮点数和复数。

        实例

        输出结果为:

        函数之间或类的方法之间用空行分隔,表示一段新的代码的开始。类和函数入口之间也用一行空行分隔,以突出函数入口的开始。

        空行与代码缩进不同,空行并不是Python语法的一部分。书写时不插入空行,Python解释器运行也不会出错。但是空行的作用在于分隔两段不同功能或含义的代码,便于日后代码的维护或重构。

        记住: 空行也是程序代码的一部分。

        执行下面的程序在按回车键后就会等待用户输入:

        以上代码中 ," "在结果输出前会输出两个新的空行。一旦用户按下 enter 键时,程序将退出。

        Python可以在同一行中使用多条语句,语句之间使用分号(;)分割,以下是一个简单的实例:

        执行以上代码,输出结果为:

        缩进相同的一组语句构成一个代码块,我们称之代码组。

        像if、while、def和class这样的复合语句,首行以关键字开始,以冒号( : )结束,该行之后的一行或多行代码构成代码组。

        我们将首行及后面的代码组称为一个子句(clause)。

        如下实例:

        print 默认输出是换行的,如果要实现不换行需要在变量末尾加上 end="" :

        以上实例执行结果为:

        在 python 用 import 或者 from...import 来导入相应的模块。

        将整个模块(somemodule)导入,格式为: import somemodule

        从某个模块中导入某个函数,格式为: from somemodule import somefunction

        从某个模块中导入多个函数,格式为: from somemodule import firstfunc, secondfunc, thirdfunc

        将某个模块中的全部函数导入,格式为: from somemodule import *

        import sys print ( ' ================Python import mode========================== ' ) ; print ( ' 命令行参数为: ' ) for i in sys . argv : print ( i ) print ( ' python 路径为 ' , sys . path )

        from sys import argv , path # 导入特定的成员 print ( ' ================python from import=================================== ' ) print ( ' path: ' , path ) # 因为已经导入path成员,所以此处引用时不需要加sys.path

        很多程序可以执行一些操作来查看一些基本信息,Python可以使用-h参数查看各参数帮助信息:

Panoptic-FlashOcc:目前速度和精度最优的全景占用预测网络

       宣传一下小伙伴最新的工作Panoptic-FlashOcc,这是一种高效且易于部署的全景占用预测框架(基于之前工作 FlashOcc),在Occ3DnuScenes上不仅取得了最快的推理速度,也取得了最好的精度。

       全景占用(Panoptic occupancy)提出了一个新的挑战,它旨在将实例占用(instance occupancy)和语义占用(semantic occupancy)整合到统一的框架中。然而,全景占用仍然缺乏高效的解决方案。在本文中,我们提出了Panoptic-FlashOcc,这是一个简单、稳健、实时的2D图像特征框架。基于FlashOcc的轻量级设计,我们的方法在单个网络中同时学习语义占用和类别感知的实例聚类,联合实现了全景占用。这种方法有效地解决了三维voxel-level中高内存和计算量大的缺陷。Panoptic-FlashOcc以其简单高效的设计,便于部署,展示了在全景占用预测方面的显著成就。在Occ3D-nuScenes基准测试中,它取得了.5的RayIoU和.1的mIoU,用于语义占用,运行速度高达.9 FPS。此外,它在全景占用方面获得了.0的RayPQ,伴随着.2 FPS的快速推理速度。这些结果在速度和准确性方面都超过了现有方法的性能。源代码和训练模型可以在以下github仓库找到: / Yzichen/FlashOCC。

       在本节中,我们概述了如何利用所提出的实例中心将全景属性集成到语义占用任务中。我们首先在第3.1节提供架构的概述。然后,我们在第3.2节深入到占用头,它预测每个体素的分割标签。随后,在第3.3节中,我们详细阐述了中心度头,它被用来生成类别感知的实例中心。最后,在第3.4节中,我们描述了全景占用处理,它作为一个高效的后处理模块,用于生成全景占用。

       如图2所示,Panoptic-FlashOcc由四个主要部分组成:BEV生成、语义占用预测、中心度头和全景占用处理。BEV生成模块将环视图像转换为BEV特征[公式],其中H、W和C分别表示特征的高度、宽度和通道维度。这个转换是通过使用图像编码器、视图转换和BEV编码器来实现的,这些可以直接从[, , , ]中采纳。为了确保在边缘芯片上高效部署,我们坚持使用FlashOCC[]的配置,其中ResNet[8]被用作图像编码器,LSS[9, ]作为视图转换器,ResNet和FPN被用作BEV编码器。

       语义占用预测模块以上述扁平化的BEV特征[公式]作为输入,并生成语义占用结果[公式],其中[公式]表示垂直于BEV平面的体素数量。同时,中心度头分别生成类别感知的热图[公式]和实例中心的回归张量[公式],其中[公式] 代表"thing"类别的语义数量。

       最后,语义占用结果[公式]和上述实例中心信息通过全景占用处理,生成全景预测[公式]。需要注意的是,全景占用处理作为后处理步骤,不涉及任何梯度反向传播。

       为确保方案轻量且易于部署,语义占用预测模块的架构直接继承自FlashOCC[]。它由一个占用头和一个channel-to-height的模块组成,能够预测"thing"和"stuff"类别的语义标签。占用头是一个子模块,包含三个2D卷积层。根据[, ]中提出的损失设置,损失函数通过引入距离感知(distance-aware)的focal loss[公式] [],改进了FlashOcc中使用的pixel-wise交叉熵损失。此外,为了增强3D语义场景完成(Semantic Scene Completion, SSC)处理遮挡区域的能力,采用了语义亲和损失 [公式] [2]和几何亲和损失 [公式]。此外,lovasz-softmax损失[公式] []也被引入到训练框架中。

       我们框架中提出的centerness head,有两个目的:如图2底部中心块所示,中心度头包括中心回归头和中心热图头。两个模块都包含三个卷积层,搭配3×3的核心。Center Heatmap Head. 中心点表示对于"thing"和"stuff"的重要性已在包括目标检测[9, , , ]、实例分割[6]和全景分割[3, ]等多项研究中得到广泛证明。在训练过程中,gt实例中心度值使用2D高斯分布进行编码,其标准差等于标注实例的对角线大小。focal loss被用来最小化预测的class-aware热力图[公式]与对应gt之间的差异。

       全景占用处理模块充当实例标签的分配模块,设计得既简单又有效。它完全依赖于矩阵运算和逻辑运算,不包含任何可训练参数。这种设计使得全景占用处理的实现直接而高效。

       给定class-aware热力图[公式],我们通过局部最大置信度提取候选实例中心索引。具体是将maxpool应用于[公式],kernel大小为3×3,找到那些被maxpool筛选出的索引。这个过程类似于目标检测中的非极大值抑制(NMS)。随后,保留置信度最高的前个索引,并使用顺序得分阈值[公式](设置为0.3)来过滤置信度低的索引。最后,我们获得了[公式]个实例中心索引提案[公式],其中[公式]、[公式]和[公式]分别代表沿[公式]、[公式]和[公式]轴的索引。[公式]的值对应于相应实例的语义标签。使用中心回归张量[公式],我们可以进一步获得与精确的3D位置和语义标签配对的实例中心提案,表示为[公式]:

       [公式]

       这里的[公式] 和 [公式] 分别代表沿 [公式] 轴和 [公式] 轴的体素大小,[公式] 是沿 [公式] 轴的感知范围。

       我们使用一个简单的最近邻分配模块来确定[公式]中每个体素的实例ID。Algorithm 1给出了相关处理的伪代码。给定语义占用[公式]和实例中心[公式]作为输入,最近邻分配模块输出全景占用[公式]。首先,我们将实例ID号[公式]初始化为0。对于语义标签中的每个类别[公式](共有[公式]个语义类别),我们首先收集在[公式]中值为[公式]的索引集[公式]。然后,我们根据[公式]是否属于“stuff”对象或“thing”对象,采取不同的处理方式。

       这些结果在速度和准确性方面都超过了现有方法的性能。在具有挑战性的Occ3DnuScenes测试中,Panoptic-FlashOcc不仅取得了最快的推理速度,也取得了最好的精度。这使得它成为目前速度和精度最优的全景占用预测网络。

       总结:本文介绍了Panoptic-FlashOcc,这是一种高效且易于部署的全景占用预测框架。它基于已建立的FlashOcc,通过整合centerness head和全景占用处理,将语义占用增强为全景占用。Panoptic-FlashOcc在具有挑战性的Occ3DnuScenes测试中不仅取得了最快的推理速度,也取得了最好的精度。