Загрузить модель onnx в C ++ opencv dnn
Я получаю следующую ошибку при загрузке модели onnx в C++ с использованием данного кода. Что я делаю неправильно? Пожалуйста, помогите мне решить эту проблему.
terminate
вызывается после выдачи экземпляра 'cv :: Exception'what(): OpenCV(4.1.0)/home/Downloads/opencv-4.1.0/modules/dnn/src/dnn.cpp:524: error:(-2: неопределенная ошибка) Невозможно создать слой «StatefulPartitionedCall / inception_resnet_v1 / AvgPool / Mean_Squeeze__1416:0» типа «Squeeze» в функции 'getLayerInstance'Прервано (ядро выгружено)
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/dnn/dnn.hpp>
using namespace std;
using namespace cv;
using namespace dnn;
int main()
{
// load the neural network model
cv::dnn::Net net = cv::dnn::readNetFromONNX("model.onnx");
}
Я получил model.onnx с помощью следующего преобразования convert: python3 -m tf2onnx.convert --saved-model /savedmodel / model --output model.onnx
версия opencv: 4.1.0 как на C++, так и на Python
2 ответа
Если вы используете tf2 и если ваши веса находятся в формате .h5, вы сможете избавиться от проблем с onnx. вы можете сгенерировать .pb из вашего .h5, а затем легко использовать в своей программе на С++. Для создания .pb используйте следующий код:
после этого с помощью opencv вы сможете импортировать свою модель и наслаждаться!
import tensorflow as tf
from tensorflow import keras
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
from tensorflow.keras.models import load_model
import numpy as np
#path of the directory where you want to save your model
frozen_out_path = '/path.../freez/' # name of the .pb file
frozen_graph_filename = "freez_graph_6cls_try1" #“frozen_graph”
model = load_model("/cls_vgg16_6_cl.h5")
# model = ""# Your model# Convert Keras model to ConcreteFunction
full_model = tf.function(lambda x: model(x))
full_model = full_model.get_concrete_function(
tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))# Get frozen ConcreteFunction
frozen_func = convert_variables_to_constants_v2(full_model)
frozen_func.graph.as_graph_def()
layers = [op.name for op in frozen_func.graph.get_operations()]
print("-" * 60)
print("Frozen model layers: ")
for layer in layers:
print(layer)
print("-" * 60)
print("Frozen model inputs: ")
print(frozen_func.inputs)
print("Frozen model outputs: ")
print(frozen_func.outputs)# Save frozen graph to disk
tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
logdir=frozen_out_path,
name=f"{frozen_graph_filename}.pb",
as_text=False)# Save its text representation
tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
logdir=frozen_out_path,
name=f"{frozen_graph_filename}.pbtxt",
as_text=True)
Модель, которую вы используете, имеет динамическую форму ввода. OpenCV DNN не поддерживает модели ONNX с динамической формой ввода [Ref] . Однако вы можете загрузить модель ONNX с фиксированной формой ввода и сделать вывод с другими формами ввода, используя OpenCV DNN.
Вы можете скачать face_detection_yunet_2022mar.onnx, который является версией используемой вами модели с фиксированной формой ввода.
Вы можете успешно загрузить и использовать модель со следующим кодом в OpenCV 4.6.0-dev.
cv::String fd_modelPath = "face_detection_yunet_2022mar.onnx";
float scoreThreshold = 0.9;
float nmsThreshold = 0.3;
int topK = 5000;
cv::Ptr<cv::FaceDetectorYN> detector = cv::FaceDetectorYN::create(fd_modelPath, "", cv::Size(320, 320), scoreThreshold, nmsThreshold, topK);
КАК ПРЕОБРАЗОВАТЬ ДИНАМИЧЕСКУЮ ФОРМУ ВВОДА В ФИКСИРОВАННУЮ? Пожалуйста, прочтите эту страницу .
КАК ЧИТАТЬ ФОРМАТ SAVEDMODEL В OPENCV DNN?
# In python 3.6 to 3.10
# load frozengraph.pb
net = cv2.dnn.readNet(path2frozengraph)
# You can easily convert your model to frozengraph using
# https://github.com/fisakhan/convert_model_x2y
# preprocess input if needed
imgn = (img-127.5)/128.0# preprocess input if needed
imgn = imgn.astype(np.float32)# convert to float32 if needed
# opencv dnn way of pre-processing (must be NCHW in cv2 dnn)
input_blob = cv2.dnn.blobFromImage(imgn, 1, (100,100), 0, swapRB=False, crop=False)
# inference
net.setInput(input_blob)
feature_vector_dnn = net.forward()