自定义Detectron2实例分割模型转框架后推理无检测结果问题
解决Detectron2模型转OpenVINO/TorchScript后无检测结果的思路
1. 对齐输入预处理逻辑
原生DefaultPredictor会自动完成图像归一化、尺寸调整、通道转换等预处理,导出后的模型需要完全复现这些步骤,否则会导致特征不匹配:
- 确认均值/方差与训练一致:Detectron2默认用
[103.53, 116.28, 123.675](BGR顺序),如果自定义过,导出后必须同步处理 - 保持尺寸调整逻辑:原生用
ResizeShortestEdge,不要随意改成固定尺寸 - 通道顺序:原生是BGR,避免误转成RGB
手动复现预处理的示例代码:
from detectron2.data.transforms import ResizeShortestEdge, apply_transform_gens import torch # 加载配置 cfg = get_cfg() cfg.merge_from_file(config_path) # 复用原生推理的预处理配置 transform_gen = ResizeShortestEdge( [cfg.INPUT.MIN_SIZE_TEST, cfg.INPUT.MIN_SIZE_TEST], cfg.INPUT.MAX_SIZE_TEST ) # 处理图像 image_transformed = apply_transform_gens([transform_gen], im)[0] # 转换为模型输入格式:CHW Tensor,减去均值/除以方差 input_tensor = torch.as_tensor(image_transformed.astype("float32").transpose(2, 0, 1)) input_tensor -= torch.tensor(cfg.MODEL.PIXEL_MEAN).view(3, 1, 1) input_tensor /= torch.tensor(cfg.MODEL.PIXEL_STD).view(3, 1, 1) # 添加batch维度 sample_input = input_tensor.unsqueeze(0)
2. 同步导出与推理的模型配置
导出时必须确保模型的关键参数和原生推理完全一致:
- 用OpenVINO转换前,先正确加载配置再构建模型:
cfg = get_cfg() cfg.merge_from_file(config_path) cfg.MODEL.WEIGHTS = weights_path cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.7 cfg.MODEL.DEVICE='cpu' model = build_model(cfg) DetectionCheckpointer(model).load(cfg.MODEL.WEIGHTS) model.eval() - 用官方导出工具时,在命令行追加自定义配置:
python ../detectron2-main/tools/deploy/export_model.py \ --config-file ../detectron2-main/configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml \ --output torchscript_model \ --format torchscript \ --sample-image ../data/test.JPG \ --export-method tracing \ MODEL.DEVICE cpu \ MODEL.WEIGHTS ../model/custom_trained_model.pth \ MODEL.ROI_HEADS.NUM_CLASSES 1 \ MODEL.ROI_HEADS.SCORE_THRESH_TEST 0.7
3. 补全后处理步骤
原生DefaultPredictor会自动执行阈值过滤、mask resize等后处理,但导出模型(尤其是用do_postprocess=False时)仅返回原始输出,需要手动补全:
from detectron2.structures import Boxes, Instances, BitMasks # 以OpenVINO输出为例,假设输出顺序为boxes, classes, masks, scores, image_size boxes = torch.tensor(results[0]) scores = torch.tensor(results[3]) masks = torch.tensor(results[2]) image_size = tuple(results[4]) # 过滤低置信度实例 keep = scores > cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST boxes = boxes[keep] scores = scores[keep] masks = masks[keep] # 构建Instances对象并调整mask尺寸 instances = Instances(image_size) instances.pred_boxes = Boxes(boxes) instances.scores = scores instances.pred_classes = torch.tensor(results[1])[keep] instances.pred_masks = BitMasks(masks).resize(image_size).tensor
4. 验证导出样本的有效性
导出TorchScript/OpenVINO时使用的sample_input必须是包含目标实例的有效图像,如果用无目标图像做tracing,模型可能会被错误优化掉检测分支。同时要确保样本的形状、数据类型和原生推理完全一致。
5. 对比导出前后的原始输出
在导出前先获取原生模型的原始输出,再和导出后的模型输出对比,定位问题环节:
# 原生模型原始输出(关闭后处理) inputs = [{"image": sample_input}] native_raw_output = model.inference(inputs, do_postprocess=False)[0] # 导出模型的输出 ov_raw_output = compiled_model(sample_input) # 对比box数值差异 print(torch.tensor(ov_raw_output[0]) - native_raw_output[0])
如果数值差异大,说明导出过程存在配置或精度问题;如果数值一致但后处理无结果,说明是阈值或后处理逻辑问题。
内容的提问来源于stack exchange,提问作者lpe
相关产品推荐
相关产品推荐

