news 2026/9/25 7:21:25

PaddleSeg PanopticSeg 全景分割标签编码协议全解:pan_id 生成、解码与源码级实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PaddleSeg PanopticSeg 全景分割标签编码协议全解:pan_id 生成、解码与源码级实践
  • 人工智能
  • 计算机视觉
  • 预训练

【免费下载链接】PaddleSeg

Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting, 3D Segmentation, etc.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleSeg
点击查看免费下载

本文围绕 PaddleSeg 仓库中 contrib/PanopticSeg 全景分割工具包所使用的标签编码协议展开。全景分割(Panoptic Segmentation)将语义分割(semantic segmentation)与实例分割(instance segmentation)统一到同一张标注图上,每个像素不仅携带"属于哪个类别"的信息,还携带"属于该类别的第几个实例"的信息。读懂这套pan_id编码协议,是理解 PanopticSeg 数据预处理、模型后处理、可视化与 PQ(Panoptic Quality)评测的前提。读完本文,你将掌握pan_id的数学构成、thing/stuff/未知像素三类标签的编码规则、默认常量label_divisor的由来,以及该协议在数据加载、后处理和评测链路中的真实调用方式。

1. 协议总览:一张图上每个像素的pan_id

在 PanopticSeg 工具包中,全景分割图(无论是数据集提供的参考标签图,还是模型推理输出的预测图)的每个像素值都被称为pan_id(panoptic ID)。协议规定:

假设共有c个类别,最大实例个数为n,则pan_id的取值范围为0到c * label_divisor + n(闭区间)。

也就是说,pan_id不是简单的类别编号,而是把"类别维度"与"实例维度"压缩进同一个整数。这一设计的核心收益是:一张单通道整型图即可同时表达语义与实例信息,无需为二者维护两张独立标签图;同时,任意一个pan_id都可以通过除法和取模运算唯一地还原出(cat_id, ins_id)二元组,便于评测与可视化。

2. 三种标签的编码规则

2.1 thing 类别(可数物体类)

对于 thing 类(如人、车、动物等可以逐个计数的物体类别),pan_id由类别 ID 与实例 ID 联合编码:

pan_id = (cat_id + 1) * label_divisor + ins_id

其中:

  • cat_id是类别 ID,从0开始计数;
  • ins_id是实例 ID,从1开始计数。

注意两个细节:类别部分带+1偏移,实例 ID 从1而不是0起步。这两点都是为了让编码结果严格避开"未知标签"的保留值0,并让 stuff 类与 thing 类在数值空间上自然分层(见下文)。

2.2 stuff 类(不可数区域类)

对于 stuff 类(如天空、地面、墙壁等背景区域,不区分个体),pan_id不再附加实例分量:

pan_id = (cat_id + 1) * label_divisor

等价于ins_id = 0的特例。stuff 像素的pan_id恰好落在其类别区间内的"基准位置"上,即pan_id % label_divisor == 0。这一性质被工具包直接利用来判定"该标签是否属于 crowd / 未分实例区域"(见第 5 节的is_crowd)。

2.3 未知标签

对于无法确定结果或未标注的像素,pan_id统一取值为0。由于cat_id + 1 >= 1且 stuff 编码最小值为1 * label_divisor = 1000,0在编码空间中是独立保留的,不会与任何合法标签冲突。

2.4 常量label_divisor

label_divisor是一个预设常量,用于在数值空间中划分"类别段"与"实例段"的宽度。协议规定其默认值为1000。以默认值为例,cat_id = 0的 thing 类第 1 个实例编码为1001,cat_id = 0的 stuff 类编码为1000,而cat_id = 1的 thing 类第 3 个实例编码为2003,等等。可以直观理解为:每个类别占用连续 1000 个 ID 号段,其中(cat_id+1)*1000为该类 stuff 基准,其后的若干正整数为该类各实例。

3. 源码中的编码与解码实现

3.1encode.py:协议的唯一权威实现

协议的数学公式在 paddlepanseg/utils/encode.py 中被完整落地,共 3 个函数:

_CAT_ID_OFFSET = 1 def decode_pan_id(pan_id, label_divisor): return (pan_id // label_divisor) - _CAT_ID_OFFSET, pan_id % label_divisor def encode_pan_id(cat_id, label_divisor, ins_id=0): return (cat_id + _CAT_ID_OFFSET) * label_divisor + ins_id def is_crowd(pan_id, label_divisor): return pan_id % label_divisor == 0
  • encode_pan_id(cat_id, label_divisor, ins_id=0)与文档公式一一对应,ins_id缺省为0,即默认编码 stuff 标签;
  • decode_pan_id(pan_id, label_divisor)是编码的逆运算:pan_id // label_divisor - 1得到cat_id,pan_id % label_divisor得到ins_id(stuff 时为0);
  • is_crowd(pan_id, label_divisor)利用ins_id == 0的性质判定该 ID 是否属于未分实例的 crowd/stuff 区域。

源码文件头部的注释TODO: Make the encoding system object-oriented and configurable.也提示我们:目前这套编码以模块级函数形式存在,工具包仍以label_divisor作为唯一可调参数。

3.2 从 COCO 标注到三张标签图:DecodeLabels

数据预处理阶段是编码协议最核心的消费方。在 paddlepanseg/transforms/transforms.py 的DecodeLabels中,工具包把 COCO 风格的 JSON 标注(segments_info,其中id为原始标注 ID、category_id为原始类别 ID、iscrowd标记是否属于拥挤区域)重编码为统一的pan_id:

class DecodeLabels(object): def __init__(self, label_divisor, ignore_index): self.label_divisor = label_divisor self.ignore_index = ignore_index def __call__(self, data): raw_label = data['label'] segments_info = data['ann'] thing_ids = set(data['thing_ids']) ins_label = np.zeros_like(raw_label, dtype='int64') sem_label = np.full_like(raw_label, self.ignore_index, dtype='int64') pan_label = np.zeros_like(raw_label, dtype='int64') ins_id = 0 class_id_tracker = Counter() for seg in segments_info: id_ = seg['id'] mask = (raw_label == id_) cat_id = seg['category_id'] sem_label[mask] = cat_id if cat_id in thing_ids: if seg['iscrowd'] == 0: # Do not include crowded instances in `ins_label` ins_id += 1 ins_label[mask] = ins_id # Re-encode `pan_id` using `cat_id` and tracked class instance id class_id_tracker[cat_id] += 1 pan_id = encode_pan_id( cat_id, self.label_divisor, ins_id=class_id_tracker[cat_id]) pan_label[mask] = pan_id else: pan_id = encode_pan_id(cat_id, self.label_divisor) pan_label[mask] = pan_id seg['id'] = pan_id ...

该实现透露了三个重要的工程细节:

  1. 实例 ID 按类别分别计数:class_id_tracker以cat_id为键分别计数,因此每个类别的实例都从 1 开始编号,而非全局连续编号——这与第 2 节公式中"ins_id是该类别内的实例 ID"的语义严格一致;
  2. crowd 区域只参与 pan 编码:iscrowd == 1的区域不写入ins_label,但仍会通过class_id_tracker占用一个实例计数并生成对应的pan_id;
  3. 一图三用:同一份标注被展开为ins_label(纯实例图)、sem_label(纯语义图,背景像素填ignore_index=255)和pan_label(pan_id全景图),训练与评测阶段按需取用。

4. 配置层面的串联:label_divisor从 YAML 到运行时

label_divisor不仅在数据侧生效,还贯穿后处理器与评测器,因此它在配置文件中被统一声明并通过 YAML 锚点(anchor)共享。以 Mask2Former COCO 配置 configs/mask2former/mask2former_resnet50_os16_coco_1024x1024_bs4_370k.yml 为例:

num_classes: &num_classes 133 ignore_index: &ignore_index 255 label_divisor: &label_divisor 1000 ... train_dataset: type: COCO ... label_divisor: *label_divisor num_classes: *num_classes ignore_index: *ignore_index val_dataset: ... - type: DecodeLabels label_divisor: *label_divisor ignore_index: *ignore_index ...

同一套&label_divisor 1000锚点被train_dataset、val_dataset以及后处理器postprocessor多处复用,保证数据编码、模型输出重编码与评测三方使用完全一致的除数。Panoptic DeepLab 的 Cityscapes 配置 configs/panoptic_deeplab/panoptic_deeplab_resnet50_os32_cityscapes_1025x513_bs8_90k.yml 同样遵循这一模式。

从源码看,label_divisor有多级默认值兜底机制:

  • 配置解析层:paddlepanseg/cvlibs/config.py 中_set_attr_if_not_exists(pp_cfg, 'label_divisor', 1000),未配置时写入默认值1000;
  • 数据集层:paddlepanseg/datasets/base_dataset.py 中PanopticDataset定义类常量LABEL_DIVISOR = 1000,构造参数label_divisor=None时自动回退到该类常量;
  • 后处理器层:Postprocessor基类与PanopticDeepLabPostprocessor、MaskFormerPostprocessor的构造参数均带label_divisor=1000默认值。

因此即便用户完全不写该字段,协议也能以默认值1000正常工作;而 COCO、Cityscapes 等数据集的类别数均远小于 1000,默认除数在工程上是安全的。

5. 编码协议在后处理与评测中的应用

5.1 PanopticDeepLab 后处理:重编码预测结果

模型输出的原始张量并不是pan_id图,需要后处理器按同一协议重新编码。在 paddlepanseg/postprocessors/panoptic_deeplab_pp.py 的_merge_semantic_and_instance中:

  • thing 实例先经中心点检测、像素分组得到实例图,再对每个实例的掩码在其语义类内做多数投票(majority voting)确定class_id,并通过class_id_tracker按类计实例,随后调用encode_pan_id(class_id, self.label_divisor, ins_id=new_ins_id)写入pan_seg;
  • stuff 区域则要求语义预测一致且面积不小于stuff_area(默认 2048 像素),直接调用encode_pan_id(class_id, self.label_divisor)(即ins_id=0)写入。

由此,预测全景图与参考标签共用同一套数值空间,评测时可以直接逐像素比对。

5.2 PQ 评测:从pan_id还原cat_id

Panoptic Quality(PQ)评测需要把预测的每个pan_id映射回类别。在 paddlepanseg/utils/evaluation/pan_seg_evaluator.py 中:

labels, labels_cnt = np.unique(pred, return_counts=True) for label, label_cnt in zip(labels, labels_cnt): if label == VOID: # id==0 stands for area to be ignored continue cat_id, _ = decode_pan_id(label, self.label_divisor) ...
  • 未知像素(pan_id == 0)在评测时被直接跳过;
  • 其余每个pan_id都通过decode_pan_id还原出cat_id并组装预测标注字典,随后与 GT 标注做匹配与混淆矩阵统计。

同理,实例分割评测器 paddlepanseg/utils/evaluation/ins_seg_evaluator.py 也通过decode_pan_id(i, self.label_divisor)解析类别,并用is_crowd(i, self.label_divisor)跳过未分实例的区域。

5.3 可视化:按类取色 + 按实例抖动

编码协议同样服务于可视化。在 paddlepanseg/utils/visualize.py 的visualize_panoptic中,逐一遍历图中唯一的pan_id,通过decode_pan_id(lab, label_divisor)得到(cat_id, ins_id):基础色取自类别的 colormap;当ins_id > 0时,在基础色附近做随机抖动生成该实例专属颜色,从而让同一类别下的不同实例在视觉上可区分。这正是"单通道pan_id图能支撑完整彩色全景可视化"的原因。

6. 数值示例与自检

为便于理解,下面用label_divisor = 1000给出几个具体编码:

场景cat_idins_idpan_id 计算pan_id
thing 类第 1 个实例01(0+1)×1000 + 11001
thing 类第 2 个实例02(0+1)×1000 + 21002
thing 类第 1 个实例11(1+1)×1000 + 12001
stuff 类20(2+1)×1000 + 03000
未知 / 未标注———0

反向验证:pan_id = 2001时,decode_pan_id(2001, 1000)得到(2001 // 1000 - 1, 2001 % 1000) = (1, 1),与编码输入一致;而pan_id = 3000时is_crowd(3000, 1000)返回True,符合 stuff 语义。

7. 协议要点小结

  • 单图双语义:pan_id一张单通道图同时编码语义类别与实例序号,pan_id = (cat_id + 1) * label_divisor + ins_id;
  • thing 与 stuff 分层:thing 使用ins_id >= 1,stuff 退化为ins_id = 0,二者在数值上不重叠,且均可由% label_divisor快速区分;
  • 0号保留:pan_id = 0专用于未知/未标注像素,评测时按 VOID 忽略;
  • label_divisor默认 1000:在配置、数据集、后处理器与评测器四层均有默认值兜底,可通过 YAML 锚点全局统一定制;
  • 全链路一致:数据加载(DecodeLabels)、模型后处理(encode_pan_id重编码)、PQ 评测(decode_pan_id还原)与可视化(decode_pan_id取色)共用 utils/encode.py 中的同一套编解码函数,确保训练、推理与评估的数值口径完全统一。

如需进一步了解该协议在完整数据流程中的位置,可继续阅读 quick_start_en.md、full_features_en.md 与 dev_guide_en.md,或直接对照 mask2former 配置 与 panoptic_deeplab 配置 验证各环节的label_divisor取值。

  • 人工智能
  • 计算机视觉
  • 预训练

【免费下载链接】PaddleSeg

Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting, 3D Segmentation, etc.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleSeg
点击查看免费下载

相关推荐

上一篇:Aidoku:iOS终极免费漫画阅读神器
下一篇:WinPmem:Windows内存取证的终极完整指南 🚀

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 7:20:16

Atlas 300V 24G昇腾AI推理卡部署YOLO模型实战:从环境搭建到性能调优

1. 项目背景:Atlas 300V 24G到底是不是一张运算加速卡先回答那个被问得最多的问题:Atlas 300V 24G是运算加速卡吗?是,但它不是那种你在个人电脑里见过的显卡。Atlas 300V是华为昇腾生态下的AI推理加速卡,核心芯片用的是…

作者头像 李华
网站建设 2026/9/25 7:18:56

视频专网系统安全技术方案:从边界防护到计算加固的实战指南

简介:视频专网系统安全是安防工程与网络建设中不可忽视的环节,该PDF资料围绕视频专网面临的前端入侵、网络滥用、数据泄露等风险,给出了从安全体系设计到分域防护建设的完整思路,面向系统集成、安防工程和网络运维人员。内容共分三…

作者头像 李华
网站建设 2026/9/25 7:14:38

STM32F103C8T6环境监测项目全解析:从原理图到Proteus仿真

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 7:14:21

Windows 11无线网卡故障根因与实战修复指南

1. 为什么Windows 11无线网卡故障让人特别头疼——不是驱动装错了,是系统底层逻辑变了Windows 11的无线网卡问题,和Win10、Win7时代完全不是一个量级。我从2021年Beta版开始就持续跟踪Win11网络栈重构,到2024年26H2预览版,已经处理…

作者头像 李华
网站建设 2026/9/25 7:13:53

3 个阶段跑通 RVC 变声器:从新手环境自检到首个音色模型

3 个阶段跑通 RVC 变声器&#xff1a;从新手环境自检到首个音色模型 【免费下载链接】Retrieval-based-Voice-Conversion-WebUI Easily train a good VC model with voice data < 10 mins! 项目地址: https://gitcode.com/GitHub_Trending/re/Retrieval-based-Voice-Conve…

作者头像 李华