
DeepLab 全景分割评测指标实战Panoptic Quality 与 Parsing Covering 的实现原理与两种评估流程【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models本篇聚焦 TensorFlow Models 仓库 DeepLab 项目中的全景分割Panoptic Segmentation又称 Whole Image Parsing评测体系详解实例级 Panoptic QualityPQ与区域级 Parsing CoveringPC两项指标的定义、偏置来源与源码实现并给出两种可直接落地的评估方案——基于 COCO 格式结果的 Python 离线评测eval_coco_format.py与基于tf.py_func的 TensorFlow 在线流式评测streaming_metrics.py。读完本文读者将能够在 COCO Panoptic 数据集或自有数据集上正确配置并运行 PQ/PC 评测并理解每个参数背后的实现逻辑。一、什么是 Whole Image Parsing全景分割评测Whole Image Parsing整图解析也称 Panoptic Segmentation全景分割是对语义分割与实例分割的泛化它为图像中的每个像素同时赋予语义类别标签与实例标签——对背景类stuff如天空、路面给出逐像素的语义分割对前景物体类thing如行人、车辆给出实例级分割。这一任务由来已久Tu et al., 2005 的 Image Parsing但早期工作往往用各自独立的指标分别评估语义分割结果与目标检测结果。Kirillov et al. 在 2018 年提出统一的实例级指标 Panoptic QualityPQ[arXiv:1801.00868]并被 COCO、Mapillary Vistas 等基准采用。DeepLab 团队Yang et al., DeeperLab: Single-Shot Image Parser, arXiv:1902.05093指出实例级 PQ 指标往往不成比例地强调小实例的解析质量且偏向 thing 类而轻视 stuff 类。为此他们把此前用于类别无关分割质量评估的 Covering 指标Arbelaez et al., PAMI 2011适配到整图解析任务上提出了区域级指标Parsing CoveringPC。仓库在 research/deeplab/evaluation/ 目录下同时提供了 PQ 与 PC 的完整实现模块构成如下文件职责base_metric.py抽象基类SegmentationMetric定义评测接口与类别/实例标签编码panoptic_quality.pyPQ 指标的 Python 实现PanopticQuality类parsing_covering.pyPC 指标的 Python 实现ParsingCovering类eval_coco_format.pyCOCO 格式结果的离线评测入口含多进程并行streaming_metrics.pyTensorFlow 图模式下的流式streamingPQ/PC 指标eval_coco_format_test.py与官方 COCO PanopticAPI 对拍的单元测试testdata/评测用的小型 GT/Pred 样例数据coco_gt.json、coco_pred.json及 ID 图像二、Panoptic QualityPQ定义、偏置与源码实现2.1 指标定义给定真值分割 S 与预测分割 SPQ 定义为公式图见 equation_pq.pngR 与 R 分别是真值区域region与预测区域|TP|、|FP|、|FN| 分别为匹配成功、误检与漏检的实例数量匹配判据为 IoU 0.5 的阈值。展开来看PQ SQ × RQSQSegmentation Quality是所有匹配实例对 IoU 的平均RQRecognition Quality等价于检测层面的 F1 分数IoU 阈值 0.5 下的 TP/FP/FN 统计。PQ 的关键性质同一 stuff 类的全部区域被当作一个实例处理且完全不考虑实例大小。10×10 像素的实例与 1000×1000 像素的实例对指标贡献相同。因此PQ 对小区域的误检false positives格外敏感——这也是为什么 COCO 官方评测代码中会提示删掉小区域可以刷高分数这类启发式操作官方源码中甚至会打印一条警告提醒使用者把本实现的结果与 COCO 官方 API 对拍因为微小数值差异0.1%在四舍五入后可能被放大见 eval_coco_format.py#L104-L110 中_build_metric对pq分支的 warning。因此文档的结论是当应用对任意尺寸实例的解析质量都同等重视时PQ 是合适的指标。2.2 源码实现要点panoptic_quality.py从源码结构看PQ 的统计完全发生在逐图比较阶段累积量按类per-class保存。核心逻辑在PanopticQuality.compare_and_accumulatepanoptic_quality.py#L52-L159标签编码先用基类的_naively_combine_labelsbase_metric.py#L78-L81把 (category, instance) 二元组压成一个整数segment_id category * max_instances_per_category instance再编码出交叉标签intersection_id gt_segment_id * offset pred_segment_id用一次np.unique(..., return_countsTrue)即可得到所有 (真值区域, 预测区域) 交集中的像素数。offset必须大于可能出现的最大segment_id数即最大唯一标签数COCO 常用256*256。TP 判定遍历有非空交集的同类别区域对计算IoU intersection / union其中 union 会剔除预测区域中落在真值 void 像素上的部分IoU 0.5即记为一个 TP并累加iou_per_class与tp_per_class。FN / FP 判定未匹配上的真值区域计 FNvoid 类除外未匹配上的预测区域计 FP但如果该预测区域超过一半面积落在真值的 ignoredvoid/crowd区域上则不惩罚——这与 COCO 官方行为一致。指标合成result_per_category按PQ_c SQ_c × RQ_c逐类计算RQ_c TP / (TP 0.5·FN 0.5·FP)最终结果对所有有效类非 ignored 且TPFNFP ≠ 0的类取平均panoptic_quality.py#L161-L174 的_valid_categories。detailed_results还支持按is_thing布尔数组把结果拆分为All / Things / Stuff三个组分别报告 PQ、SQ、RQ 与类数 Nprint_detailed_results则用 prettytable 输出这张表。merge方法只需把iou/tp/fn/fp四个 per-class 向量相加这正是多进程并行评测能成立的前提。三、Parsing CoveringPC面向大目标更重要的应用场景3.1 动机与定义在自动驾驶等应用中近处即画面中大的目标远比远处的小目标重要。PC 通过让实例面积参与加权来体现这一点其公式图见 equation_pc.png为S_i 与 S_i 分别表示第 i 个语义类的真值分割与预测分割N_i 是 S_i 中真值区域的总像素数单类 CoveringCov_i 的计算方式与原 Covering 指标相同只是只考虑 S_i 的真值区域与 S_i 的预测区域PC 所有 C 个语义类的 Cov_i 的平均。类级别的覆盖度本质上就是按真值面积加权的最大 IoUSC(c) Σ_{R∈S} (|R| · max_{R∈S} O(R,R)) / Σ_{R∈S} |R|见 parsing_covering.py#L43-L56 的类文档字符串。PC 与 PQ 的一个显著区别是PC 不涉及匹配也就没有 IoU 阈值。为了平等对待 thing 与 stuffPC 允许部分正确的分割获得部分得分——文档中给出的例子是若三棵同样大小的树有一棵被完美分割那么无论把 tree 当 stuff 还是 thing模型得到的 PC 部分得分都相同。3.2 源码实现要点parsing_covering.pyParsingCovering.compare_and_accumulateparsing_covering.py#L85-L164的实现路径与 PQ 不同分配三个[num_categories, max_instances_per_category]的数组分别记录每类真值实例面积gt_areas、预测实例面积pred_areas、以及每类真值实例对应的最大 IoUmax_ious同样用intersection_id gt_segment_id * offset pred_segment_id编码交叉标签并统计交集面积同时把每个真值实例与它相交的预测实例记录到intersections[(category, gt_instance)]对每个真值实例在其所有同类别相交预测实例中取最大 IoU无阈值过滤若normalize_by_image_sizeTrue先把gt_areas除以图像总像素数再累加——这使大分辨率图像中的小目标不会因为像素面积大而占便宜累积weighted_iou_per_class Σ(max_ious × gt_areas)与gt_area_per_class Σ(gt_areas)单类 PC 即weighted_iou / gt_arearesult_per_categoryparsing_covering.py#L166-L169。PC 的detailed_results同样支持 All / Things / Stuff 分组但每组只输出pc与类数n两个字段parsing_covering.py#L185-L209。四、方案一COCO 格式的 Python 离线评测eval_coco_format.py4.1 前置准备安装 COCO Panoptic APICOCO 结果格式已被多个基准采用因此仓库提供eval_coco_format函数来评估以 COCO 格式 保存的结果JSON 描述标注结构ID 图像给出每个区域的像素位置。使用前需要先把官方 COCO panoptic segmentation 任务 APIpanopticapi下载到本地目录并把research/与该目录加入PYTHONPATH。仓库的 research/deeplab/g3doc/installation.md Add Libraries to PYTHONPATH 一节给出了具体做法# From tensorflow/models/research/ export PYTHONPATH$PYTHONPATH:pwd:pwd/slim # [Optional] for panoptic evaluation, you might need panopticapi: touch ${PANOPTICAPI_DIR}/panopticapi/__init__.py export PYTHONPATH$PYTHONPATH:${PANOPTICAPI_DIR}/panopticapi4.2 eval_coco_format 的完整参数说明核心函数签名eval_coco_format.py#L222-L233eval_coco_format(gt_json_file, pred_json_file, gt_folderNone, pred_folderNone, metricpq, num_categories201, ignored_label0, max_instances_per_category256, intersection_offsetNone, normalize_by_image_sizeTrue, num_workers0, print_digits3)各参数含义与默认值默认值均按 COCO panoptic segmentation 数据集设定评估其他数据集时需要自行修改gt_json_fileCOCO 格式真值标注 JSON 文件路径必填pred_json_file待评估预测结果的 JSON 文件路径必填gt_folder存放真值 panoptic 格式 ID 图像的文件夹用于把标注映射到图像区域。不传时默认为gt_json_file去掉.json后缀的路径eval_coco_format.py#L272-L275pred_folder存放预测 ID 图像的文件夹默认规则同上metric指标名pc或pq由_build_metric分发到ParsingCovering/PanopticQuality见 eval_coco_format.py#L97-L116num_categories数据集的分割类别总数COCO 为 201含 voidignored_label评测中忽略的类别 id例如 COCO panoptic 的 void 标签 0max_instances_per_category每个类别允许的最大实例数用于保证实例标签唯一参与segment_id编码intersection_offset最大唯一标签数用于生成交集区域的唯一 id。不传时自动取(num_categories 1) * max_instances_per_categoryeval_coco_format.py#L276-L277normalize_by_image_sizePC 评测时是否用图像大小归一化真值实例面积对pc生效默认 Truenum_workers并行 worker 数。正整数时按图像切分派发到多进程-1时使用multiprocessing.cpu_count()0 表示单进程print_digits结果汇总输出的有效数字位数。在 COCO 上评测 PQ 时用户只需提供两个 JSON 文件路径即可gt_folder/pred_folder/其余参数都有可用默认值。4.3 命令行运行方式脚本通过 absl flags 暴露了同名命令行参数gt_json_file、gt_folder、pred_json_file、pred_folder四个为必填项eval_coco_format.py#L335-L338。仓库提供的小型样例数据位于 research/deeplab/evaluation/testdata/coco_gt.json、coco_pred.json及coco_gt/、coco_pred/两个 ID 图像目录可以直接照下面的形态运行cd research/deeplab/evaluation python eval_coco_format.py \ --gt_json_file../testdata/coco_gt.json \ --gt_folder../testdata/coco_gt \ --pred_json_file../testdata/coco_pred.json \ --pred_folder../testdata/coco_pred \ --metricpq --num_categories7 \ --intersection_offset65536其中--intersection_offset65536即 256×256与单元测试中的取值一致--num_categories7对应样例数据 6 个类别 void。切换到--metricpc即评估 Parsing Covering。4.4 内部流程与多进程并行从源码结构看eval_coco_format的执行链路为eval_coco_format.py#L268-L321读取 GT/Pred 两个 JSON按image_id用_matched_annotations配对eval_coco_format.py#L119-L128_build_metric构造指标聚合器num_workers 0时启动多进程每对标注作为任务放入work_queue各 worker 用独立的指标实例对分到的图像调用_compute_metric内部通过_split_panoptic把 COCO ID 图像segments_info拆成逐像素的 category 图与 instance 图其中 GT 侧iscrowd区域会被并入 ignored 类而预测侧忽略iscrowd标记与官方代码行为一致最后通过merge合并回主聚合器_is_thing_array从 JSON 的categories中解析isthing字段得到 per-category 的 thing/stuff 布尔数组并校验类别 id 是否连续缺失时会打 warning调用print_detailed_results打印 All/Things/Stuff 分组结果表并返回detailed_results(is_thing)字典。函数最终返回的是分组结果字典形如{All: {pq:..., sq:..., rq:..., n:...}, Things: {...}, Stuff: {...}}PC 模式为{All: {pc:..., n:...}, ...}。五、方案二TensorFlow 在线streaming评测如果希望在训练/评估流程内以类似tf.contrib.metrics.streaming_mean_iou的方式累积指标仓库提供streaming_metrics.streaming_panoptic_quality与streaming_metrics.streaming_parsing_coveringstreaming_metrics.py。5.1 构造 metric_mapfrom deeplab.evaluation import streaming_metrics metric_map {} metric_map[panoptic_quality] streaming_metrics.streaming_panoptic_quality( category_label, instance_label, category_prediction, instance_prediction, num_classes201, max_instances_per_category256, ignored_label0, offset256*256) metric_map[parsing_covering] streaming_metrics.streaming_parsing_covering( category_label, instance_label, category_prediction, instance_prediction, num_classes201, max_instances_per_category256, ignored_label0, offset256*256, normalize_by_image_sizeTrue) metrics_to_values, metrics_to_updates slim.metrics.aggregate_metric_map( metric_map)其中category_label与instance_label分别是真值的语义分割与实例分割。它们与 COCO 全景分割格式的关系为panoptic_label category_label * max_instances_per_category instance_labelcategory_prediction与instance_prediction分别是预测的语义分割与实例分割metric_map是保存 PQ 与 PC 流式结果的字典。两个 streaming 函数都要求图模式tf.executing_eagerly()为真时抛出RuntimeError见 streaming_metrics.py#L106-L107。其内部实现是用tf.py_func把整图交给上文的 Python 实现_panoptic_quality_helper/_parsing_covering_helper逐图计算 per-class 中间量再由_running_total维护的LOCAL_VARIABLES累加器跨批次累积streaming_metrics.py#L40-L54streaming_panoptic_quality返回形状[6, num_classes]的张量6 行依次为pq、sq、rq、total_tp、total_fn、total_fpupdate ops 为 4 个累加操作streaming_parsing_covering返回[3, num_classes]3 行依次为per-class PC、逐类加权 IoU 总和、逐类真值区域面积总和。5.2 汇总为 tf.summary评测值张量需要按类展开后过滤无效类再求均值。仓库文档给出的完整汇总模板对panoptic_quality与parsing_covering分别处理如下summary_ops [] for metric_name, metric_value in metrics_to_values.iteritems(): if metric_name panoptic_quality: [pq, sq, rq, total_tp, total_fn, total_fp] tf.unstack( metric_value, 6, axis0) panoptic_metrics { pq: pq, # Panoptic quality. sq: sq, # Segmentation quality. rq: rq, # Recognition quality. total_tp: total_tp, total_fn: total_fn, total_fp: total_fp, } # 有效类 非 void 类 且 (tp fn fp) ! 0 的类 valid_classes tf.logical_and( tf.not_equal(tf.range(0, num_classes), void_label), tf.not_equal(total_tp total_fn total_fp, 0)) for target_metric, target_value in panoptic_metrics.iteritems(): output_metric_name {}_{}.format(metric_name, target_metric) op tf.summary.scalar( output_metric_name, tf.reduce_mean(tf.boolean_mask(target_value, valid_classes))) op tf.Print(op, [target_value], output_metric_name _classwise: , summarizenum_classes) op tf.Print( op, [tf.reduce_mean(tf.boolean_mask(target_value, valid_classes))], output_metric_name _mean: , summarize1) summary_ops.append(op) elif metric_name parsing_covering: [per_class_covering, total_per_class_weighted_ious, total_per_class_gt_areas] tf.unstack(metric_value, 3, axis0) valid_classes tf.logical_and( tf.not_equal(tf.range(0, num_classes), void_label), tf.not_equal( total_per_class_weighted_ious total_per_class_gt_areas, 0)) op tf.summary.scalar( metric_name, tf.reduce_mean(tf.boolean_mask(per_class_covering, valid_classes))) op tf.Print(op, [per_class_covering], metric_name _classwise: , summarizenum_classes) op tf.Print( op, [tf.reduce_mean( tf.boolean_mask(per_class_covering, valid_classes))], metric_name _mean: , summarize1) summary_ops.append(op) else: raise ValueError(The metric_name %s is not supported. % metric_name)注意过滤条件与 Python 实现的_valid_categories严格对应PQ 侧忽略 void 类以及tpfnfp 0的类PC 侧忽略 void 类以及weighted_iou gt_area 0的类。5.3 接入评估循环最后按 SLIM 的评估循环驱动评测可参考 research/deeplab/eval.py——该脚本提供了一个对语义分割做 mIOU 流式评测的简单示例metric_values slim.evaluation.evaluation_loop( masterFLAGS.master, checkpoint_dirFLAGS.checkpoint_dir, logdirFLAGS.eval_logdir, num_evalsnum_batches, eval_opmetrics_to_updates.values(), final_opmetrics_to_values.values(), summary_optf.summary.merge(summary_ops), max_number_of_evaluationsFLAGS.max_number_of_evaluations, eval_interval_secsFLAGS.eval_interval_secs)六、如何验证评测结果的正确性仓库自带了可对拍的单元测试是检验环境是否搭好的最佳起点PQ 对拍官方实现eval_coco_format_test.py 的test_compare_pq_with_reference_eval在 testdata/ 样例数据上分别运行官方 panopticapi 的pq_compute与本仓库的eval_coco_format(metricpq, num_categories7, ignored_label0, max_instances_per_category256, intersection_offset256*256)断言 All/Things/Stuff 三组的 pq、sq、rq、n 完全一致PC 黄金值test_compare_pc_with_golden_value断言normalize_by_image_sizeFalse时All组pc ≈ 0.68210561n6、Things 组≈ 0.5890529n4、Stuff 组≈ 0.86821097n2test_compare_pc_with_golden_value_normalize_by_size则断言开启按图像大小归一化时All组pc ≈ 0.68214908840多进程一致性test_pc_with_multiple_workers用num_workers3并行计算结果与单进程黄金值一致验证了merge合并逻辑的正确性。streaming 侧的 streaming_metrics_test.py 则用 testdata 中的 GT/Pred 图像对如team_gt_instance.png、team_pred_class.png、team_pred_instance.png在会话中喂入单图/多图断言 PQ 的 pq/sq/rq 与 TP/FN/FP 张量逐元素取近似相等如单图 case 的result_sq ≈ [2.06104, 0.7526, 0.54069]覆盖单图、多图累积与normalize_by_image_size开/关等组合。七、指标选型与关键参数速查何时用 PQ、何时用 PC关注每个实例不论大小都应被正确解析如通用物体理解基准→ PQ关注大目标解析质量如自动驾驶中近处目标更重要、且不希望匹配阈值引入不连续性 → PC两者都支持 All/Things/Stuff 分组报告可横向比较模型在 stuff 与 thing 上的短板。关键参数速查两种方案共用同一套含义参数COCO 默认值作用num_categories201类别总数决定 per-class 数组维度ignored_label0void 类 id不参与 TP/FN/FP 统计max_instances_per_category256类别×实例数编码上限须 ≥ 单图同类最大实例数offset离线为intersection_offset(num_categories1)×256 或 256×256交叉标签编码基数须大于最大 segment_id 数normalize_by_image_sizeTrue仅 PC累加前按图像像素数归一化真值面积注意事项streaming 指标只能在图模式TF1 风格会话中使用eager 模式会抛RuntimeError离线 PQ 结果建议与 COCO 官方 API 对拍后再用于论文级汇报源码 warning 亦提醒四舍五入可能放大 0.1% 的差异默认参数按 COCO panoptic 数据集设定评估自有数据集时必须同步修改num_categories、ignored_label等取值。参考论文与 research/deeplab/evaluation/README.md 的 References 一致Image Parsing: Unifying Segmentation, Detection, and Recognition. Zhuowen Tu et al., IJCV 2005.Panoptic Segmentation. Alexander Kirillov et al., arXiv:1801.00868, 2018.Microsoft COCO: Common Objects in Context. Tsung-Yi Lin et al., ECCV 2014.The Mapillary Vistas Dataset for Semantic Understanding of Street Scenes. Gerhard Neuhold et al., ICCV 2017.DeeperLab: Single-Shot Image Parser. Tien-Ju Yang et al., arXiv:1902.05093, 2019.Contour Detection and Hierarchical Image Segmentation. Pablo Arbelaez et al., PAMI 2011.【免费下载链接】modelsModels and examples built with TensorFlow项目地址: https://gitcode.com/GitHub_Trending/mode/models创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考