Загрузить модель 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()
Другие вопросы по тегам