[Aprendizaje profundo] [Opencv] Python/C++ llama al modelo onnx [Conceptos básicos]

[Aprendizaje profundo] [Opencv] Python/C++ llama al modelo onnx [Conceptos básicos]

Consejo: El blogger ha seleccionado muchas publicaciones de blogs de grandes y las ha probado personalmente para comprobar su eficacia. Comparte sus notas e invita a todos a estudiarlas y discutirlas juntos.


Prefacio

OpenCV es una biblioteca de software multiplataforma de visión por computadora y aprendizaje automático (código abierto) publicada bajo la licencia BSD y puede ejecutarse en los sistemas operativos Linux, Windows, Android y Mac OS. El modelo entrenado en pytorch se puede exportar usando ONNX y luego cargarlo directamente usando el módulo dnn en opencv.
Directorio de aprendizaje de la serie:
[CPU] Explicación detallada del proceso del modelo Pytorch al modelo ONNX
[GPU] Explicación detallada del proceso del modelo Pytorch al formato ONNX
[modelo ONNX] Implementación rápida
[modelo ONNX] Implementación rápida de subprocesos múltiples
[modelo ONNX] Opencv llama a nx


Versión de PythonOpenCV

Instale OpenCV en la plataforma Windows

El blogger instaló el entorno anaconda en el entorno win10 y luego creó el entorno openCV necesario para ejecutar el modelo onnx.

# 搭建opencv环境
conda create -n opencv_onnx python=3.10 -y
# 激活环境
activate opencv_onnx
# 安装opencv
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

Ver versión opencv

import cv2
cv2.__version__

opencv llama al modelo onnx

Ahora el código deja de lado cualquier dependencia relacionada con pytorch y onnx, y solo usa opencv para completar todo el proceso de inferencia.

import cv2
import numpy as np

def normalizeImage(image,mean,std):
    normalized = image.astype(np.float32)
    normalized = normalized / 255.0 - mean
    normalized = normalized / std
    return normalized

def main():
    # 读取图片
    image = cv2.imread(r"./animal-1.jpg")
    # 将BGR图像转换为RGB格式
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 获取图像的大小
    ori_w, ori_h, = image.shape[0], image.shape[1]

    # 指定调整后的大小
    new_width = 416
    new_height = 416
    # 图片尺寸缩放
    resized_img = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)

    # 定义每个通道的归一化参数
    mean = np.array([0.485, 0.456, 0.406]).astype(np.float32)  # 均值
    std = np.array([0.229, 0.224, 0.225]).astype(np.float32)  # 标准差
    # 图片归一化
    normalized = normalizeImage(resized_img, mean, std)

    # 加载ONNX模型
    net = cv2.dnn.readNetFromONNX("PFNet.onnx")  # 加载训练好的识别模型
    # onnx是多输出,每个输出都会对应一个name,因此需要获取所有输出的name
    output_layer_names = net.getUnconnectedOutLayersNames()
    blob = cv2.dnn.blobFromImage(normalized)  # 由图片加载数据 这里还可以进行缩放、归一化等预处理
    # 将Blob设置为模型的输入
    net.setInput(blob)
    # 运行前向传播,将所有输出name作为参数传递
    out = net.forward(output_layer_names)
    out = np.squeeze(out[3]) * 255.0
    output = cv2.resize(out, (ori_h, ori_w), interpolation=cv2.INTER_AREA)

    # 保存图像
    cv2.imwrite('saved_opencv_python_image.png', output)

if __name__ == '__main__':
    main()


Versión C++ OpenCV

Instale OpenCV en la plataforma Windows

Descargue la dirección del archivo de instalación del sitio web oficial . El blogger usa la versión opencv-4.8.0-windows.exe y hace doble clic para ejecutarlo y descomprimirlo para obtener los siguientes archivos:
Open VS 2019: cree un nuevo proyecto--- ->Aplicación de consola---->Proyecto de configuración ----> Ruta del proyecto y marque "Colocar la solución y el proyecto en el mismo directorio ----> Haga clic en Crear.

Establezca la ruta de OpenCV: Proyecto ----> Propiedades.

Agregar Directorio de inclusión adicional: Depuración | x64 ---->C/C+±—>General---->Directorios de inclusión adicionales.

D:\C++_demo\opencv\build\x64\vc16\bin
D:\C++_demo\opencv\build\bin
D:\C++_demo\opencv\build\include
D:\C++_demo\opencv\build\include\opencv2

Vinculador: Depurar | x64---->Enlazador---->General---->Directorios de inclusión adicionales.

D:\C++_demo\opencv\build\x64\vc16\lib

Vinculador: Depurar | x64---->Enlazador---->Entrada---->Dependencias adicionales.

Busque los archivos para dependencias adicionales en D:\C++_demo\opencv\build\x64\vc16\lib.

opencv_world480d.lib

Para probar en modo Debug x64, copie el archivo opencv_world480d.dll con d al directorio de depuración de su proyecto.

Cuando no hay un directorio de depuración, debe ejecutar el código en modo Debug | x64.

D:\C++_demo\opencv\build\x64\vc16\bin
===>
D:\C++_demo\opencv_onnx\x64\Debug

El blogger aquí instaló la versión de depuración para facilitar la depuración. Los lectores pueden instalar la versión de lanzamiento, solo necesitan cambiar Depurar |

opencv llama al modelo onnx

Fácil de usar

Aquí hay una verificación simple de si opencv se instaló exitosamente. Es adecuado para muchas personas, incluidos blogueros que no están familiarizados con C ++. El código completa la lectura y visualización de imágenes simples.

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
    
    
	Mat src = imread("./animal-1.jpg");
	//没有图像输入
	if (src.empty()) {
    
    
		printf("....\n");
		return -1;
	}
	//namedWindow("输入窗口", WINDOW_FREERATIO);
	imshow("输入窗口", src);
	waitKey(0);
	destroyAllWindows();
	return 0;
}

Llame al modelo onnx

Después de convertir la versión Python de opencv a la versión c ++ correspondiente, descubrimos que los efectos de salida son exactamente los mismos: el modelo onnx se puede utilizar como una interfaz c ++ para que lo llamen otras aplicaciones.

#include <iostream>
#include <string>
#include <vector>
#include<opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
cv::Mat normalizeImage(const cv::Mat& image, const cv::Scalar& mean, const cv::Scalar& std) {
    
    
    cv::Mat normalized;
    image.convertTo(normalized, CV_32F);
    cv::subtract(normalized / 255.0, mean, normalized);
    cv::divide(normalized, std, normalized);
    return normalized;
}
int main()
{
    
       
    // 读取图片
    cv::Mat bgrImage = cv::imread("./animal-1.jpg", cv::IMREAD_COLOR);
    // 图片格式转化bgr-->rgb
    cv::Mat rgbImage;
    cv::cvtColor(bgrImage, rgbImage, cv::COLOR_BGR2RGB);
    // 获取图像的大小
    cv::Size originalSize(rgbImage.cols, rgbImage.rows);
    cv::Mat resizedImage;

    // 定义目标图像大小
    cv::Size targetSize(416, 416);
    //图片尺寸缩放
    cv::resize(rgbImage, resizedImage, targetSize, 0, 0, cv::INTER_AREA);

    // 定义每个通道的归一化参数
    cv::Scalar mean(0.485, 0.456, 0.406); // 均值
    cv::Scalar std(0.229, 0.224, 0.225);  // 标准差
    // 图片归一化
    cv::Mat normalized = normalizeImage(resizedImage, mean, std);
    
    // 加载ONNX模型
    cv::dnn::Net net = cv::dnn::readNetFromONNX("D:/C++_demo/opencv_onnx/PFNet.onnx");
    cv::Mat blob = cv::dnn::blobFromImage(normalized);
    // 将Blob设置为模型的输入
    net.setInput(blob);
    // 运行前向传播
    std::vector<cv::Mat> output_probs;
    // 获取多输出对应的名称
    std::vector<cv::String> output_layer_names = net.getUnconnectedOutLayersNames();
    net.forward(output_probs, output_layer_names);
    cv::Mat prediction = output_probs[3];
    cv::Mat mask;
    cv::resize(prediction.reshape(1, 416) * 255.0, mask, originalSize, 0, 0, cv::INTER_AREA);
    cv::imwrite("saved_opencv_c++_image.png", mask);
    return 0;
}


Resumir

Presente el proceso de llamada al modelo ONNX mediante POpencv en Python y C++ de la manera más simple y detallada posible.

Supongo que te gusta

Origin blog.csdn.net/yangyu0515/article/details/132894953
Recomendado
Clasificación