OpenCV Python加载YOLOv5 ONNX模型报Identity节点错误如何解决
问题背景
在OpenCV 4.6.0环境下调用DNN模块加载YOLOv5 ONNX模型,实现俯视视角的人员检测功能时,模型加载阶段触发运行错误。
对应的实现代码如下:
# hyper parameters INPUT_WIDTH = 640 # YOLOv5网络输入宽度 INPUT_HEIGHT = 640 # YOLOv5网络输入高度 SCORE_THRESHOLD = 0.5 # 低置信度类别过滤阈值 NMS_THRESHOLD = 0.45 # 重叠检测框NMS过滤阈值 CONFIDENCE_THRESHOLD = 0.45 # 检测结果置信度过滤阈值 BLACK = (0, 0, 0) BLUE = (255, 178, 50) YELLOW = (0, 255, 255) classes = [] person_found = False # 加载类别名称 class_files = 'yolo/coco.names' with open(class_files, 'r') as source: classes = source.read().rstrip('\n').split('\n') # 模型路径 weights = 'yolo/models/yolov5s.onnx' net = cv2.dnn.readNet(weights) # 构造输入blob:参数依次为输入图像、缩放因子、输入尺寸、均值减数值、是否交换RB通道、是否裁剪 blob = cv2.dnn.blobFromImage(frame, scalefactor=1/255, size=(INPUT_WIDTH, INPUT_HEIGHT), mean=[0, 0, 0], swapRB=True, crop=False) net.setInput(blob) outputs = net.forward(net.getUnconnectedOutLayersNames())
注意:原代码中with open块下的类名读取行缺少缩进,运行时会先触发语法错误,需要补充4空格缩进后再运行
报错信息
模型加载时抛出的完整错误日志如下:
[ERROR:0@1.622] global D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\onnx\onnx_importer.cpp (1021) cv::dnn::dnn4_v20220524::ONNXImporter::handleNode DNN/ONNX: ERROR during processing node with 1 inputs and 1 outputs: [Identity]:(onnx_node!Identity_0) from domain='ai.onnx' Traceback (most recent call last): File "D:\Unitn\Corsi\Computer vision\project\synopsis\main.py", line 25, in <module> bg_frames = find_bg_frames(video, duration, fps) File "D:\Unitn\Corsi\Computer vision\project\synopsis\utils.py", line 152, in find_bg_frames people_found = find_people_with_yolo(frame) File "D:\Unitn\Corsi\Computer vision\project\synopsis\utils.py", line 102, in find_people_with_yolo net = cv2.dnn.readNetFromONNX(weights) cv.error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\onnx\onnx_importer.cpp:1040: error: (-2:Unspecified error) in function 'cv::dnn::dnn4_v20220524::ONNXImporter::handleNode' > Node [Identity@ai.onnx]:(onnx_node!Identity_0) parse error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\dnn\src\layer.cpp:246: error: (-215:Assertion failed) inputs.size() in function 'cv::dnn::dnn4_v20220524::Layer::getMemoryShapes'
问题原因
该错误和前处理、推理逻辑代码无关,核心原因是OpenCV 4.6.0的DNN模块对新版YOLOv5导出的ONNX模型存在算子兼容性缺陷:
新版YOLOv5默认导出ONNX模型时,会在输出层添加Identity算子做节点映射,而OpenCV 4.6.0的ONNX导入器没有适配这类未绑定有效输入的Identity节点,解析时触发输入维度校验的断言错误,最终导致模型加载失败。
解决方案
可根据自身环境选择以下任意一种方案修复:
- 重新导出兼容低版本OpenCV的ONNX模型
从YOLOv5官方仓库导出ONNX模型时,指定opset版本为12,同时开启模型简化参数,自动裁剪冗余的Identity节点,导出命令参考:
导出完成后替换原有模型文件即可,不需要修改现有推理代码。python export.py --weights yolov5s.pt --include onnx --opset 12 --simplify - 升级OpenCV版本
将本地的opencv-python包升级到4.7.0及以上版本,高版本OpenCV已经修复了该类Identity算子的解析问题,不需要重新导出模型即可正常加载默认参数导出的YOLOv5 ONNX文件。 - 手动修复现有ONNX模型
如果不想升级OpenCV、也没有条件重新导出模型,可以用onnx库直接裁剪现有模型的冗余节点,修复代码参考:
后续推理时加载修复后的import onnx # 加载原有模型 model = onnx.load('yolo/models/yolov5s.onnx') # 移除输出端冗余的Identity节点 while model.graph.node[-1].op_type == 'Identity': model.graph.node.pop() # 绑定最终输出节点到模型输出 final_output = model.graph.node[-1].output[0] model.graph.output.clear() model.graph.output.append(onnx.helper.make_tensor_value_info(final_output, onnx.TensorProto.FLOAT, None)) # 保存修复后的模型 onnx.save(model, 'yolo/models/yolov5s_fixed.onnx')yolov5s_fixed.onnx文件即可。
内容的提问来源于stack exchange,提问作者Neskelogth
相关产品推荐
相关产品推荐

