mmdetection从测试到可视化:test.py参数与结果解析

发布时间:2026/10/17 12:13:36
mmdetection从测试到可视化:test.py参数与结果解析 很多人在 mmdetection 上把训练流程跑顺之后反而会卡在 test 和可视化这一步。训练哪怕跌跌撞撞也总能出个权重文件但真要验证模型效果、把检测框画回到原图上不少同学就开始找不到北test.py 到底该怎么调--out 参数要不要加生成的 pkl 里装的是什么怎么把结果变成一张能直接贴到汇报里的图更别说那些绕不开的警告和报错了。这篇文章把我自己在 mmdetection 上从测试到可视化结果的全过程完整捋一遍重点讲清楚测试脚本的执行机制、关键参数怎么选、可视化操作的三种可行方案以及评估指标应该怎么解读。适用对象是已经训完模型、想验证效果的同学也适合刚接触该框架、想知道 test 阶段完整链条的新手。下面直接进正题。1. mmdetection 测试链路分析——先搞清楚 test 到底在干什么1.1 测试工作的本质拆解mmdetection 的 test 并不只是把图片喂进模型这么简单。一个完整的测试阶段实际上由三个环节组成前向推理、后处理、指标评估或结果保存。前向推理阶段模型加载训练好的权重对输入图像提取特征并产生原始预测。但在目标检测任务里模型直接输出的往往不是最终的检测框而是一堆候选区域proposal或者密集的预测结果。后处理阶段要做的就是通过 NMS非极大值抑制等算法把这些候选结果过滤掉冗余框保留最终的检测结果。第三个环节则是两种分支如果带了 --eval脚本会调用评估模块计算 mAP、AR 等指标如果带了 --out脚本会把每个图像的预测结果序列化保存成 pkl 文件。很多教程只告诉你怎么跑一行命令却不讲这个过程导致出问题时不知道去哪个环节排查。比如可视化结果里出现大量重叠框那多半是后处理阈值设置有问题比如某个类别 AP 为 0可能是数据集标签和模型类别对不上与后处理无关。1.2 测试前必须准备的三样东西在正式执行测试之前建议先检查三样东西配置文件、权重文件和数据集标注。配置文件不仅是训练时用的 config它同样定义了测试阶段的数据管线。你需要确认 config 里的 dataset 路径是否指向了正确的测试集尤其是当你训练集和测试集存放在不同目录时这一步最容易出错。还要检查 config 中 test_pipeline 的 img_scale、flip 等参数是否符合预期。权重文件方面mmdetection 会保存两种文件epoch_x.pth 是完整的检查点包含模型参数、优化器状态和迭代次数而 best_mAP_epoch_x.pth 之类的是根据验证指标挑选的最优权重。测试时加载哪个都可以但需要注意如果你在训练过程中修改过 config测试时用的 config 必须和训练时保持一致否则权重中保存的类别数、通道数等信息会对不上轻则报错重则结果完全不可用。数据集标注也要提前检查一下。测试阶段不需要加载标注来参与前向计算但 --eval 阶段会拿预测结果和标注做比对。如果标注文件缺失、类别 id 对不上、或者图片路径失效测试虽然可能正常跑完但指标结果会是空的或出现难以理解的异常。1.3 环境验证先用一个快速推理确认链路通畅我的习惯是在跑完整的 test.py 之前先做一次小规模的快速推理验证确认环境、权重、配置这三者没有基础性的问题。具体做法很简单直接从测试集里抽两三张图片单独写一个小脚本加载模型来推理。mmdetection 的推理 API 不复杂核心就是通过 build_detector 加载配置、通过 load_checkpoint 加载权重然后调用 model 的 forward 方法或者使用 inference_detector。这一步花不了两分钟但能把绝大部分环境配置问题暴露出来比如 CUDA 版本不兼容、mmcv 和 mmdet 版本不匹配、权重缺失等等。等你确认单张图片能顺利跑出检测框再执行完整测试脚本路径就顺畅很多。这个习惯帮我避免过无数次“跑了半小时测试脚本然后发现是环境没配好”的低级问题。2. test.py 执行机制与参数配置——一条命令背后的完整逻辑2.1 tools/test.py 的运行流程mmdetection 的测试入口是仓库根目录下的 tools/test.py。执行命令后脚本内部会依次做以下几件事第一步解析命令行参数同时调用 mmcv 的 Config 类加载你指定的 config 文件。Config 类会把配置文件里的所有字典、列表转换成 Python 对象这也是之后所有模块的构建依据。第二步根据 config 中的 model 字段构建检测模型再把训练好的权重加载进去。第三步构建测试数据集和测试数据流水线。第四步遍历测试集中的所有图像按批次前向推理。第五步收集每个 batch 的预测结果根据用户指定的 --out 或 --eval 参数做保存或评估。整个流程其实和训练脚本的验证阶段非常相似。可以说test.py 是验证阶段逻辑的独立完整版只是不再涉及反向传播和优化器更新。2.2 核心参数逐一拆解test.py 提供了不少参数但实际使用频率最高的就几个我把它们拆开讲。--out 参数用来指定结果输出文件路径。它保存的是一个 pkl 格式的序列化文件里面包含了每个测试图像对应的预测结果。这里有一个常见误区--out 并不会帮你把检测框画到图像上它只是把 NumPy 格式的预测数据存下来。想可视化还得借助工具脚本或者自己写绘图代码。--eval 参数用来指定评估指标。目标检测任务一般填 bbox实例分割任务则额外加 segm。如果你测的是 VOC 格式数据集还可以用 mAP 这类指标。这个参数可以直接决定脚本最后打印出来的是哪些数值。--show 参数会在测试过程中直接把带框图像弹窗显示出来。问题是如果测试集有成百上千张图你不可能一张张看下去。而且这个参数依赖 GUI 环境在远程服务器上跑几乎必然报错。更实用的做法是用 --show-dir 指定一个输出目录脚本会把带框图像批量保存到该目录不依赖 GUI也能离线查看。--cfg-options 是一个容易被低估的参数。它允许你在命令行临时覆盖 config 中的任意配置项比如调整测试时的阈值、更换数据集的路径甚至修改 backbone 的某些参数。在调试阶段不必每次改完 config 再重跑脚本直接传这个参数会高效很多。2.3 推理阶段与训练阶段的差异这里有一个非常关键的细节模型在训练和测试阶段的 forward 行为是不同的mmdetection 通过 model.train() 和 model.eval() 来切换。在训练阶段模型会计算 loss并产生用于反向传播的中间变量在测试阶段模型只进行前向推理输出的是原始预测结果。更本质的区别在于 BatchNorm 和 Dropout 这类层的行为。BatchNorm 在训练时会统计当前 batch 的均值和方差而测试时必须使用训练阶段累积的全局统计量。如果漏了 model.eval() 这行很多模型的测试结果会非常差。mmdetection 的 test.py 已经帮你处理好了这些细节但如果你自己写推理脚本千万不要忘记调用 model.eval()同时最好用 torch.no_grad() 把梯度计算关掉。否则不仅显存占用会飙升推理速度也会慢好几倍。3. 可视化测试结果实操——三种方法按需选择3.1 直接保存图像配置 --show-dir 参数对大多数需求来说最简单可靠的可视化方式就是使用 test.py 自带的 --show-dir 参数。运行命令后脚本会在指定目录下生成每张测试图像的检测结果图文件名默认与输入图像名一致。我推荐的做法是python tools/test.py \ configs/xxx/your_config.py \ work_dirs/xxx/best_mAP_epoch_50.pth \ --show-dir work_dirs/xxx/vis_results \ --out work_dirs/xxx/test_results.pkl \ --eval bbox这条命令同时完成两件事把带框图像保存到 vis_results 目录把预测结果序列化到 test_results.pkl并计算 bbox 相关的评估指标。如果测试集图像分辨率很高建议先确认一下磁盘空间因为保存的图是原图尺寸成百上千张高分辨率图会占用不少空间。3.2 使用 pkl 结果做二次可视化有时候你不想重新跑一遍测试或者想调整可视化参数比如置信度阈值、线宽、颜色这时 pkl 文件的作用就体现出来了。test.py 生成的 pkl 是一个 list每个元素对应一张测试图像。每个元素的格式通常是 (bbox_results, segm_results) 或直接是 bbox_results具体取决于模型是否包含分割分支。bbox_results 是一个长度为类别数的列表每个类别对应一个二维数组数组的行是检测框每行格式为 [x1, y1, x2, y2, score]。你可以通过以下脚本加载 pkl 并重新绘制import mmcv import numpy as np from mmdet.apis import init_detector from mmdet.core import bbox2result # 加载测试结果 pkl results mmcv.load(work_dirs/xxx/test_results.pkl) # 加载模型用于获取类别名称 model init_detector(configs/xxx/your_config.py, work_dirs/xxx/best_mAP_epoch_50.pth, devicecuda:0) CLASSES model.CLASSES # 假设绘制第一张图 img mmcv.imread(path/to/first_image.jpg) img_show img.copy() for i, class_name in enumerate(CLASSES): dets results[0][i] # 第0张图、第i个类别的预测结果 for det in dets: x1, y1, x2, y2, score det[:5] if score 0.3: # 根据自己的需要调整置信度阈值 continue cv2.rectangle(img_show, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(img_show, f{class_name} {score:.2f}, (int(x1), int(y1)-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) mmcv.imwrite(img_show, output.jpg)这样做的好处是灵活你可以按自己的需求过滤结果、调整样式甚至把多个模型的结果画在同一张图上做对比。3.3 自定义可视化脚本的进阶用法除了直接画框有时候我们还需要更多信息辅助分析比如画出热力图、统计框的尺寸分布、或者把置信度散点图画出来。这些需求用 test.py 内置的可视化功能实现不了但基于 pkl 文件就可以做到。例如分析模型在低置信度区间的表现可以用以下思路遍历 pkl 中所有图像的所有类别框统计不同置信度区间的框数量和平均 IoU。通过这种方式你会发现自己训练的模型是不是“宁可多框也不漏框”的风格或者是不是“过度保守”导致大量漏检。对检测框做尺寸分布分析也很有用画出框宽度和高度的散点图判断模型在小目标和大目标上的表现是否均衡。实践中很多模型的 AP 被拉低不是因为整体效果差而是因为某一类尺寸的目标几乎完全没有检出。这种分析在纯指标层面是看不出端倪的只有可视化才能帮你定位问题。3.4 保存格式与输出效果调整在可视化输出时有几个细节会影响最终结果的可用性。首先是图像保存格式。如果你只是快速查看建议输出成 JPG如果要在论文或汇报中使用原则上应该保存成 PNG 无损格式避免 JPG 压缩带来的边缘毛刺。其次是框的线宽和字体大小。小分辨率图像用默认的 2px 线宽可能已经覆盖了目标本身需根据图像的尺寸适当调整。一个简单的经验是线宽取图像宽度的千分之一到两千分之一字体大小类似。最后是置信度阈值的选择。可视化时阈值设得太低画面上会堆满低置信度的噪声框难以阅读设得太高则可能看不到模型的潜在错误。我的经验是在模型正常收敛的情况下0.3 是一个比较合理的初始阈值既能展示大部分有效检测又不会产生过多视觉干扰。4. 测试与可视化过程中的高频问题排查4.1 显存溢出CUDA out of memory测试阶段比训练阶段更吃显存的现象其实不常见但当你增大批次大小或者测试大尺寸图像时依旧可能遇到显存不足的情况。解决思路有三个方向。第一个方向是降低 batch sizetest.py 中可以通过修改 data 配置的 samples_per_gpu 来控制也可以在命令行用 --cfg-options data.test.samples_per_gpu1 来临时覆盖。第二个方向是减小输入图像尺寸调整 test_pipeline 中的 img_scale 参数能显著降低显存占用缺点是会影响检测精度。第三个方向是检查代码中是否开了梯度计算如果自己写推理脚本务必在 forward 前用 torch.no_grad() 包裹。也要注意mmdetection 的某些模型如 Cascade R-CNN、Mask R-CNN 等本身结构较复杂即使单张图也很吃显存。这种情况下优先考虑降低输入尺寸而不是强行加大显存。4.2 pkl 文件加载失败或字段对不上pkl 文件是用 mmcv.load 加载的。如果你发现加载后的对象结构和预期不符先确认两件事一是生成 pkl 时模型的类别数是否和现在加载时 config 的类别数一致二是 pkl 是否由同一个版本的 mmdetection 生成。版本兼容性是一个大坑。mmdetection 在 1.x 和 2.x 版本之间输出结果的格式有过变化甚至在 2.x 的早期和后期版本之间某些字段也略有不同。如果你在加载 pkl 时遇到 KeyError 或者维度不匹配的报错最直接的解决方法是换用生成 pkl 时的那个版本的 mmdetection 再做加载。另外pkl 文件在跨平台传输时也可能出问题。如果文件是在 Linux 上生成的在 Windows 上用 mmcv.load 读取一般没问题但如果是 Python 2.x 生成的 pkl在 Python 3.x 环境中加载大概率会报编码错误这种情况只能回退环境或者重新生成。4.3 可视化输出图像空白或检测框错位如果你发现可视化图像里完全没有检测框或者框的位置明显不对排查顺序如下第一确认置信度阈值是否设得过高导致全部框都被过滤了第二确认可视化脚本里的坐标格式是 [x1, y1, x2, y2] 还是 [x, y, w, h]画图时要尤其注意这一点第三确认你画图的图像是不是和测试时输入的是同一张图如果图像尺寸被 resize 过检测框坐标是针对原图还是缩放后图像的坐标系这也是常见的错误来源。mmdetection 默认情况下测试时如果开启了 test_pipeline 中的 resize检测框会同步映射回原图尺寸所以从 pkl 读出的坐标应该是原图坐标系直接画到原图上不需要额外变换。但如果你在自定义脚本里对图像进行了其他预处理比如 padding 或裁切就必须自己维护坐标变换。4.4 指标读数为 0 或异常偏高这种情况一旦出现基本先怀疑数据标签和配置文件是不是匹配。某个类别的 AP 为 0优先检查测试集的标注中是否存在这个类别的目标。如果测试集本身就没有该类的任何真实目标AP 按定义就是 0并不是模型的问题。另一种常见原因是类别顺序不一致。比如训练时的 class_id 顺序和测试时 config 里的 class 列表不同或者 label_map 配置错了会导致模型输出的类别序号和标注的类别序号错位最终表现为每个类别指标都异常。还有一种是数据格式问题。如果标注框的坐标格式、类别编号和代码预期的不一致评估模块可能直接跳过这部分标注导致召回率和 mAP 出现奇怪的数值。遇到这种情况建议写个小脚本单独检查一条标注样本把标注内容打印出来和 config 中的 class 列表做对比。5. 评估指标到底怎么看——从数字反推模型状态5.1 mAP、AR、召回率的实际含义mmdetection 测试完成后你会看到一系列指标。最核心的是 mAPmean Average Precision它综合反映了模型在不同置信度阈值下的精确率和召回率表现。具体到输出结果VOC 格式下你会看到 mAP0.5意思是 IoU 阈值为 0.5 时的平均精度COCO 格式则更严格会输出 mAP0.5:0.95这是从 0.5 到 0.95 每隔 0.05 取一个 IoU 阈值计算的平均值。后者对定位精度的要求更高所以一般数值会比前者低不少。ARAverage Recall是 COCO 指标里的另一项它在一定程度上反映了模型“能找到多少目标”的能力与置信度阈值无关。如果你的 mAP 不高但 AR 还可以说明模型能检测到目标只是置信度排序不够好或者定位精度不够如果 AR 本身也很低说明模型直接漏掉了很多目标属于更本质的检测能力问题。小目标和大目标通常也会分开统计比如 COCO 指标里的 AP_s、AP_m、AP_l。关注这些细分指标能帮你快速判断模型在哪类尺寸上有明显短板。5.2 从指标分布反推模型问题读懂指标不是为了汇报而是为了指导下一步工作。举例来说如果你发现 AP_s小目标明显低于 AP_l大目标那可能说明模型下采样倍数过大小目标的特征已经丢失。这种情况下用高分辨率输入或者引入特征金字塔相关结构可能会带来改善。如果所有类别的 AP 都偏低但训练集 loss 已经收敛到很低就要怀疑是否过拟合。这时候增加数据增强、引入更强的正则化或者干脆早点停止训练都会有帮助。如果某个类别 AP 明显低于其他类别且该类别的训练样本数量很少这说明数据不平衡问题突出。可以考虑增加该类的采样权重或者通过数据增强手段扩充该类的样本。我个人的习惯是拿到测试指标后先不看整体 mAP而是按类别列出 AP 柱状图再按尺寸列出三个 AP 值。这两张图能快速暴露模型最明显的弱点比一个笼统的 mAP 数字有用得多。5.3 建立自己的评估与可视化基线在重复多次训练、调参、测试之后你会发现如果每次都用不同的可视化参数、不同的评估方式结果之间很难横向对比。我建议在项目初期就固定一套评估与可视化模板。这套模板可以包含统一的测试集、统一的置信度阈值、统一的图像输出尺寸、固定的指标输出格式。每次测试后保存一份包含配置信息、权重信息、指标结果的记录文件。这样做的好处是当你要比较不同训练策略的效果时或者要回溯某个历史模型的表现时有一份规整的基准可供参考。很多同学跑完一个模型就把结果丢了过几天想对比发现手头只有一张截图连当时用的权重文件都找不到了非常可惜。养成把测试结果连同 config、日志、pkl 一起归档的习惯长远来看回报极高。6. 写在最后关于测试可视化的几点个人体会我自己用 mmdetection 做了不少目标的检测项目测试流程也反复跑过很多回。这里分享几个代码之外的经验。第一不要在测试环节省时间。训练可以花十几个小时但测试阶段即使跑几万张图也很快关键在于你要拿到足够多的分析素材。宁可多生成一份 pkl 文件多保存一批可视化图像也不要等到需要对比时才发现手头没有结果。第二pkl 文件和可视化图像最好一起保存。pkl 是后续做量化分析和自定义可视化的基础而图像是快速展示和人工检查的依据。只保存 pkl 的话每次看结果都要写脚本太麻烦只保存图像的话后续想换个阈值重新画图就得重新跑测试浪费时间。第三遇到指标异常一定从数据和配置排查起不要急着怀疑模型。模型如果有大问题在训练阶段的 loss 曲线里往往已经能看出来。测试环节出现诡异数值十有八九出在标注路径、类别顺序、评估参数这些配置性问题上。冷静梳理一下测试链路比反复重跑几次测试有效得多。最后当你打算把 mmdetection 接入自己的项目或产品时建议尽早把测试和可视化流程自动化。写一个简单的脚本传入配置文件路径和权重路径自动完成测试、保存结果、生成可视化报告这一整套动作。这个脚本能为你节省大量时间也能让项目协作中的每个人对模型效果有统一、直观的认知。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询