解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态)

这篇具有很好参考价值的文章主要介绍了解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、问题来源

最近做人脸识别项目,想只用OpenCV自带的人脸检测和识别模块实现,使用OpenCV传统方法:Haar级联分类器人脸检测+LBPH算法人脸识别的教程已经有了,于是想着用OpenCV中的dnn模块来实现,dnn实现人脸检测也有(详细教程可见我的这篇博客https://blog.csdn.net/weixin_42149550/article/details/131474284),问题就是基于cnn的人脸识别咋用opencv的dnn模块实现?一番搜索,发现OpenCV的dnn模块在加载YuNet模型时会报错
从官网下载的模型文件:
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能

# 加载人脸检测模型
faceDetector = cv2.FaceDetectorYN.create('./opencvmodels/yunet.onnx', '', (320, 320))
# 加载人脸识别模型
faceRecognizer = cv2.FaceRecognizerSF_create(model='./opencvmodels/face_recognizer_fast.onnx', config='')

yunet模型加载会报错,face_recognizer_fast加载没有问题
报错提示:
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
重点看最后一句话:
error: (-215:Assertion failed) !isDynamicShape in function ‘cv::dnn::dnn4_v20221220::ONNXImporter::parseShape’

这句报错是说加载的onnx模型是动态的,但是OpenCV的cv2.FaceDetectorYN.create()不支持加载动态的模型,这里的动态指的是模型没有指定固定的输入参数。

我们通过netron(https://netron.app/)来查看yunet.onnx的模型结构(部分)
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
从图中可以看到,官网上下载的模型结构batch_size,height,width都是未知的,这在OpenCV中是不支持的,虽然问题知道了,但是在网上查了几天都没找到解决办法!!!
PS:遇到bug真的不能陷进去,放一放,平静一下,第二天说不定就能解决了

二、解决办法

非常感谢这几篇文章,让我对onnx模型有了更多的了解,最后终于摸索出来(把自己给感动了)
如何修改已有的ONNX模型 https://tool.4xseo.com/a/15892.html
模型部署入门教程(五):ONNX 模型的修改与调试
https://zhuanlan.zhihu.com/p/516920606?utm_medium=social&utm_oi=800114666985648128&utm_id=0
官网讨论
https://github.com/opencv/opencv/issues/23288


先看onnx解释:
ONNX 在底层是用 Protobuf 定义的。Protobuf,全称 Protocol Buffer,是 Google 提出的一套表示和序列化数据的机制。使用 Protobuf 时,用户需要先写一份数据定义文件,再根据这份定义文件把数据存储进一份二进制文件。可以说,数据定义文件就是数据类,二进制文件就是数据类的实例。

神经网络本质上是一个计算图。计算图的节点是算子,边是参与运算的张量。而通过可视化 ONNX 模型,我们知道 ONNX 记录了所有算子节点的属性信息,并把参与运算的张量信息存储在算子节点的输入输出信息中。事实上,ONNX 模型的结构可以用类图大致表示如下:
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
我们把yunet.onnx模型先加载进来

# 使用onnx模块
model = onnx.load('./opencvmodels/yunet.onnx')
onnx.checker.check_model(model) # 验证Onnx模型是否准确

通过验证说明OpenCV提供的onnx模型是没有问题的。
接着我们打印出yunet的计算图

# 计算图太大了
print(model.graph)

解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
可以看到initializer中储存了一个节点的数据信息,其中的名字name都是跟netron中看到的一一对应,因为数据太多了,看不全,我们只把计算图的ninput输入部分打印出来,看看是怎么样的

print(model.graph.input)

[name: “input”
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_param: “batch_size”
}
dim {
dim_value: 3
}
dim {
dim_param: “height”
}
dim {
dim_param: “width”
}
}
}
}
]

可以看到输入结构在onnx中是一个可迭代的列表容器,包含了name名字,type类型,type中又定义了输入的维度,现在的思路就是要把shape中的dim_param: "height"和dim_param: "width"换成固定的值即dim_value,我们一层一层来打印:

for input_node in model.graph.input:
    print(input_node)

name: “input”
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_param: “batch_size”
}
dim {
dim_value: 3
}
dim {
dim_param: “height”
}
dim {
dim_param: “width”
}
}
}
}

我们遍历输入结构,可以看到外层的括号去掉了,我们接着向下层索引:

for input_node in model.graph.input:
    print(input_node.type)

tensor_type {
elem_type: 1
shape {
dim {
dim_param: “batch_size”
}
dim {
dim_value: 3
}
dim {
dim_param: “height”
}
dim {
dim_param: “width”
}
}
}

for input_node in model.graph.input:
    print(input_node.type.tensor_type.shape)

dim {
dim_param: “batch_size”
}
dim {
dim_value: 3
}
dim {
dim_param: “height”
}
dim {
dim_param: “width”
}

那么思路就有了,我们只要索引到dim这一层,然后把其中的dim_param: "height"和dim_param: "width"替换成固定的dim_value: 320就可以了

for input_node in model.graph.input:
    # print(input_node.type.tensor_type.shape)
    input_node.type.tensor_type.shape.dim[2].dim_value = 320
    input_node.type.tensor_type.shape.dim[3].dim_value = 320
    print(input_node.type.tensor_type.shape)

想要的结果出现了!!!

dim {
dim_param: “batch_size”
}
dim {
dim_value: 3
}
dim {
dim_value: 320
}
dim {
dim_value: 320
}

接下来我们重新验证模型有没有问题,然后将模型保存成新的模型

onnx.checker.check_model(model)
onnx.save(model, 'opencvmodels/new_yunet.onnx')

我们重新在netron中查看一下模型结构
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
新的yunet模型的输入已经改成固定输入尺寸,下面我们来测试一下模型能不能用

recognize_net = cv2.dnn.readNetFromONNX('./opencvmodels/new_yunet.onnx')
dnn_faceDetector = cv2.FaceDetectorYN_create(model="./opencvmodels/new_yunet.onnx", config="", input_size=(320, 320))

没有报错!!! 呜呜呜~~~~

来看一下人脸识别效果
(借用彭于晏哥哥的照片)
解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
人脸对齐
cv2.FaceDetectorYN还封装了人脸对齐,超级方便有木有

face1_align = faceRecognizer.alignCrop(image1, face1_detect[1])

解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
人脸检测
检测的准确率很高!!

解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态),OpenCV-Python,人脸识别,深度学习,opencv,dnn,人工智能
人脸匹配结果,判断出这是同一个人,这里使用了两种距离匹配方法:余弦距离和L2距离,结果一样。
大功告成!!!文章来源地址https://www.toymoban.com/news/detail-755559.html

到了这里,关于解决Opencv dnn模块无法使用onnx模型的问题(将onnx的动态输入改成静态)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV中DNN模块

             OpenCV自3.3版本开始,加入了对深度学习网络的支持,即DNN模块,它支持主流的深度学习框架生成与到处模型的加载。         OpenCV中的深度学习模块(DNN)只提供了推理功能,不涉及模型的训练,支持多种深度学习框架,比如TensorFlow,Caffe,Torch和Darknet。 轻量

    2024年02月15日
    浏览(31)
  • C++使用onnxruntime/opencv对onnx模型进行推理(附代码)

    结果: current image classification : French bulldog, possible : 16.17 对两张图片同时进行推理 current image classification : French bulldog, possible : 16.17 current image class ification : hare, possible : 8.47 https://download.csdn.net/download/qq_44747572/87810859 https://blog.csdn.net/qq_44747572/article/details/131631153

    2024年02月05日
    浏览(38)
  • OpenCV图像处理——DNN模块

    图像处理总目录←点击这里 随着计算机视觉的流行,opencv 也专门开发了 dnn 模块来实现 深度神经网络相关 的功能; opencv 无法训练模型,但它支持载入其他深度学习框架训练好的模型,并使用该模型进行预测 inference; opencv 在载入模型时会使用 dnn 模块对模型进行重写,使得

    2024年02月12日
    浏览(26)
  • [C++]使用纯opencv去部署yolov9的onnx模型

    【介绍】 部署 YOLOv9 ONNX 模型在 OpenCV 的 C++ 环境中涉及一系列步骤。以下是一个简化的部署方案概述,以及相关的文案。 部署方案概述: 模型准备 :首先,你需要确保你有 YOLOv9 的 ONNX 模型文件。这个文件包含了模型的结构和权重。 环境配置 :安装 OpenCV 库,并确保它支持

    2024年03月13日
    浏览(52)
  • Opencv-DNN模块之官方指导:利用DNN模块实现深度学习应用:分类、分割、检测、跟踪等

    本文根据 Deep Learning with OpenCV DNN Module: A Definitive Guide 中相关内容进行翻译整理而得,用于今后的学习和工程。   § 00 前   言 ---   机器视觉研究领域从上个世纪六十年后期就已创立。图像分类和物体检测是计算机视觉领域中的一些最古老的的问题,研究者为解决它进行

    2024年02月05日
    浏览(48)
  • 【ONNX】使用 C++ 调用 ONNX 格式的 PyTorch 深度学习模型进行预测(Windows, C++, PyTorch, ONNX, Visual Studio, OpenCV)

    要使用 ONNX 模型进行预测,就需要使用 onnx runtime 首先到 ONNX 官网查询所需的版本 这里使用的 Windows,同时装了 CUDA 下面的链接可以进入到安装网址 https://www.nuget.org/packages/Microsoft.ML.OnnxRuntime.Gpu 安装命令为: 首先打开 Visual Studio 2019 新建一个用于测试的项目 右键点击项目,可

    2024年02月09日
    浏览(43)
  • [C++]使用yolov8的onnx模型仅用opencv和bytetrack实现目标追踪

    【官方框架地址】 yolov8: https://github.com/ultralytics/ultralytics bytetrack: https://github.com/ifzhang/ByteTrack 【算法介绍】 随着人工智能技术的不断发展,目标追踪已成为计算机视觉领域的重要研究方向。Yolov8和ByTetrack作为当前先进的算法,当它们结合使用时,能够显著提升目标追踪的准

    2024年01月24日
    浏览(35)
  • opencv dnn模块 示例(19) 目标检测 object_detection 之 yolox

    YOLOX是旷视科技在2021年发表,对标YOLO v5。YOLOX中引入了当年的黑科技主要有三点,decoupled head、anchor-free以及advanced label assigning strategy(SimOTA)。YOLOX的性能如何呢,可以参考原论文图一如下图所示。YOLOX比当年的YOLO v5略好一点,并且利用YOLOX获得当年的Streaming Perception Challenge第一

    2024年02月06日
    浏览(35)
  • opencv dnn模块 示例(16) 目标检测 object_detection 之 yolov4

    博客【opencv dnn模块 示例(3) 目标检测 object_detection (2) YOLO object detection】 测试了yolov3 及之前系列的模型,有在博客【opencv dnn模块 示例(15) opencv4.2版本dnn支持cuda加速(vs2015异常解决)】 说明了如何使用dnn模块进行cuda加速推理。 本文说明yolo v4的网络改进和测试情况。 yolo v1~

    2024年02月07日
    浏览(31)
  • opencv dnn模块 示例(25) 目标检测 object_detection 之 yolov9

    YOLOv9 是 YOLOv7 研究团队推出的最新目标检测网络,它是 YOLO(You Only Look Once)系列的最新迭代。YOLOv9 在设计上旨在解决深度学习中信息瓶颈问题,并提高模型在不同任务上的准确性和参数效率。 Programmable Gradient Information (PGI) :YOLOv9 引入了可编程梯度信息(PGI)的概念,这是

    2024年04月29日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包